title: FormData File Upload with Progress Listener Content-Type header missing
body: <p>I am building a client-server application with a java-server (no JSP, just <code>com.sun.net.httpserver.HttpServer;</code>) and web frontend as client. I use WebSockets for communication and want to upload files with XMLHttpRequests and FormData (i followed this post <a href="https://stackoverflow.com/questions/14002393/track-ajax-post-progress-for-fileupload-using-jquery-ajax-and-formdata">Track ajax post progress for fileupload using jquery ajax and FormData</a>). I want to track the upload progress with <code>xhr.upload.onprogress</code>, but as soon as i add a listener such as</p>
  
  <pre><code>xhr.upload.onprogress = function(e) {...};
  </code></pre>
  
  <p>or</p>
  
  <pre><code>xhr.upload.addEventListener("progress", function (e) {...}, false);
  </code></pre>
  
  <p>i get an serverside error like this:</p>
  
  <pre><code>org.apache.commons.fileupload.FileUploadBase$InvalidContentTypeException: the request doesn't contain a multipart/form-data or multipart/mixed stream, content type header is null
      at org.apache.commons.fileupload.FileUploadBase$FileItemIteratorImpl.&lt;init&gt;(FileUploadBase.java:948)
      at org.apache.commons.fileupload.FileUploadBase.getItemIterator(FileUploadBase.java:310)
      at org.apache.commons.fileupload.FileUploadBase.parseRequest(FileUploadBase.java:334)
      at com.awaker.server.HttpUploadServer.handle(HttpUploadServer.java:42)
      at com.sun.net.httpserver.Filter$Chain.doFilter(Filter.java:79)
      at sun.net.httpserver.AuthFilter.doFilter(AuthFilter.java:83)
      at com.sun.net.httpserver.Filter$Chain.doFilter(Filter.java:82)
      at sun.net.httpserver.ServerImpl$Exchange$LinkHandler.handle(ServerImpl.java:675)
      at com.sun.net.httpserver.Filter$Chain.doFilter(Filter.java:79)
      at sun.net.httpserver.ServerImpl$Exchange.run(ServerImpl.java:647)
      at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
      at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
      at java.lang.Thread.run(Thread.java:745)
  </code></pre>
  
  <p>I use the <a href="https://commons.apache.org/proper/commons-fileupload/index.html" rel="nofollow noreferrer">Apache Commons FileUpload</a> framework for handling upload requests.</p>
  
  <p>This occurs in Firefox and Opera (the only browsers i tested), and while the correct Content-Type headers are listed in Firebug/developer console, the server does not receives this header (same goes for Content-Length header).</p>
  
  <p>It doesn't matter if i use jQuery ajax</p>
  
  <pre><code>$.ajax({
             url: "http://host...",
             type: "POST",
             data: ajaxData,
             cache: false,
             contentType: false,
             processData: false,
             xhr: function () {
                 var xhr = jQuery.ajaxSettings.xhr();
                 if (xhr.upload) {
                     xhr.upload.addEventListener("progress", function (e) {
                      console.log("hello");
                      }, false);
                 }
                 return xhr;
             }
         });
  </code></pre>
  
  <p>or vanilla js </p>
  
  <pre><code>var xhr = new XMLHttpRequest();
  xhr.upload.onprogress = uploader.uploadProgress;
  xhr.open("POST", "http://host...");
  xhr.send(formData);
  </code></pre>
  
  <p>i always get the same error.
  As soon as i remove the onprogress-handler, everything works fine.
  I already tried this <a href="https://stackoverflow.com/questions/27744470/formdata-boundary-missing-from-content-type-in-post-request-header">FormData boundary missing from content-type in POST request header</a>, but this doesn't work for me, too.</p>
  
  <p>Does anybody know how to solve this?
  Thank you!</p>
  
  <p>Edit: 
  The ajaxData are generated from an drop event:</p>
  
  <pre><code>    var droppedFiles = e.originalEvent.dataTransfer.files;
      var ajaxData = new FormData();
      ajaxData.append("file", droppedFiles[0]);
  </code></pre>
  
  <p>The contentType: false option lets jQuery/XHR automatically add the Content-Type header with the neccessary boundary. This option is required, it doesn't work without it.</p>
  
  <p>Edit2: 
  This works fine</p>
  
  <pre><code>$.ajax({
             url: "http://host...",
             type: "POST",
             data: ajaxData,
             cache: false,
             contentType: false,
             processData: false,
             xhr: function () {
                 var xhr = jQuery.ajaxSettings.xhr();
                 return xhr;
             }
         });
  </code></pre>
  
  <p>It seems that only adding the progress listener makes a difference.</p>
  
  <p>Edit3:
  Here is the serverside code that throws the error:</p>
  
  <pre><code>@Override
  public void handle(HttpExchange httpExchange) throws IOException {
      DiskFileItemFactory diskFileItemFactory = new DiskFileItemFactory();
      ServletFileUpload fileUpload = new ServletFileUpload(diskFileItemFactory);
  
      try {
          List&lt;FileItem&gt; result = fileUpload.parseRequest(new HttpHandlerRequestContext(httpExchange));
          (...)
      } catch (FileUploadException e) {
          e.printStackTrace();
      }
  
  }
  </code></pre>
  
  <p>i followed this answer <a href="https://stackoverflow.com/a/33827895/6655315">https://stackoverflow.com/a/33827895/6655315</a>.
  The HttpHandlerRequestContext is exactly the same as shown in the linked post.</p>
  
  <p>Edit4:
  just by adding an empty upload progress handler like this</p>
  
  <pre><code> xhr.upload.onprogress = function(e) {};
  </code></pre>
  
  <p>the received headers are changing from this</p>
  
  <pre><code>Accept-encoding: gzip, deflate
  Origin: http://localhost:63343
  Accept: */*
  Referer: http://localhost...
  Connection: keep-alive
  Host: localhost:4734
  Dnt: 1
  User-agent: Mozilla/5.0 (Windows NT 6.3; WOW64; rv:47.0) Gecko/20100101 Firefox/47.0
  Accept-language: de,en-US;q=0.7,en;q=0.3
  Content-type: multipart/form-data; boundary=---------------------------63422017421660
  Content-length: 333700
  </code></pre>
  
  <p>to this:</p>
  
  <pre><code>Accept-encoding: gzip, deflate
  Access-control-request-method: POST
  Origin: http://localhost:63343
  Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
  Connection: keep-alive
  Host: localhost:4734
  Dnt: 1
  User-agent: Mozilla/5.0 (Windows NT 6.3; WOW64; rv:47.0) Gecko/20100101 Firefox/47.0
  Accept-language: de,en-US;q=0.7,en;q=0.3
  </code></pre>