title: How to sent multipart file request using Ajax
body: <p>I can see variations on this question get asked a lot, but after trying many of the suggestions here I still can't get this to quite work. Basically, I have an HTML form that on submit makes a POST multipartfile request to the server:</p>
  
  <pre><code>&lt;form class="resource-checkout-form" method="POST" enctype="multipart/form-data" 
          id="resourcefilecheckoutform" action="/uploadAndCheckout"&gt;
      &lt;input type="file" name="file" id="selectyamlfile" class="filestyle"/&gt;
  &lt;/form&gt;
  </code></pre>
  
  <p>When the value is changed (a file is selected), I have the form submit automatically:</p>
  
  <pre><code>$('#selectyamlfile').change(function() {
        $('#resourcefilecheckoutform').submit();
      });
  </code></pre>
  
  <p>To a REST interface on the server:</p>
  
  <pre><code>@ApiResponses(value = { 
          @ApiResponse(code = 200, message = "Success", response = HttpMessageInformationReturnDataBean.class),
          @ApiResponse(code = 404, message = "Not Found")}) 
  @RequestMapping(value = "/uploadAndCheckout", method = RequestMethod.POST)
  public String singleFileUpload(@RequestParam("file") MultipartFile file,
                                 RedirectAttributes redirectAttributes) {
  </code></pre>
  
  <p>So far so good, that works, and it uploads the selected file. The problem comes when I try and bypass the form submit redirect by using Ajax to do the request itself. I changed the HTML (removing the action):</p>
  
  <pre><code>&lt;form class="resource-checkout-form" method="POST" enctype="multipart/form-data" 
          id="resourcefilecheckoutform"&gt;
      &lt;input type="file" name="file" id="selectyamlfile" class="filestyle"/&gt;
  &lt;/form&gt;
  </code></pre>
  
  <p>And moved the action itself to a jquery that occurs when the form is submitted:</p>
  
  <pre><code>$('#resourcefilecheckoutform').submit(function(e){
      e.preventDefault();
      $.ajax({
          url:'/uploadAndCheckout',
          type:'POST',
          contentType: false,
          cache: false,
          processData: false,
          data:$('#resourcefilecheckoutform').serialize(),
          success:function(){
              console.log("success");
          }
      });
  }); 
  </code></pre>
  
  <p>It makes the request, but on the server side it complains that the request is not a multipart request:</p>
  
  <pre><code>org.springframework.web.multipart.MultipartException: The current request is not a multipart request
  </code></pre>
  
  <p>The number one suggestion I've found is to change the contentType to false, but I'd already done that and it didn't work. So, having searched around I tried a few things, starting with changing the contentType to multipart:</p>
  
  <pre><code>$('#resourcefilecheckoutform').submit(function(e){
      e.preventDefault();
      $.ajax({
          url:'/uploadAndCheckout',
          type:'POST',
          contentType: 'multipart/form-data',
          cache: false,
          processData: false,
          data:$('#resourcefilecheckoutform').serialize(),
          success:function(){
              console.log("success");
          }
      });
  }); 
  </code></pre>
  
  <p>But that caused an error about a missing boundary:</p>
  
  <pre><code>Caused by: java.io.IOException: org.apache.tomcat.util.http.fileupload.FileUploadException: the request was rejected because no multipart boundary was found
  </code></pre>
  
  <p>So I figured I'd add the boundary in, as suggested in some of the other threads:</p>
  
  <pre><code>$('#resourcefilecheckoutform').submit(function(e){
      e.preventDefault();
      var boundary = '--'+Math.random().toString().substr(2);
      $.ajax({
          url:'/uploadAndCheckout',
          type:'POST',
          contentType: 'multipart/form-data; boundary='+boundary,
          cache: false,
          processData: false,
          data: $('#resourcefilecheckoutform').serialize(),
          success:function(){
              console.log("success");
          }
      });
  }); 
  </code></pre>
  
  <p>But that causes a 400 - Bad Request error with no other real feedback to indicate what it didn't like. I feel like I'm dancing around some fundamental mistake that I'm just not seeing, maybe I'm grabbing the data itself wrong? Does anyone know how to achieve this?</p>