2016-07-29 3 views
0

Ich baue eine Client-Server-Anwendung mit einem Java-Server (keine JSP, nur com.sun.net.httpserver.HttpServer;) und Web-Frontend als Client. Ich benutze WebSockets für die Kommunikation und möchte Dateien mit XMLHttpRequests und FormData hochladen (ich folgte diesem Beitrag Track ajax post progress for fileupload using jquery ajax and FormData). Ich möchte mit xhr.upload.onprogress den Upload-Fortschritt verfolgen, aber sobald ich ein Zuhörer wieFormData File Upload mit Progress Listener Content-Type-Header fehlt

xhr.upload.onprogress = function(e) {...}; 

oder

xhr.upload.addEventListener("progress", function (e) {...}, false); 

ich so erhalten einen server Fehler hinzu:

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.<init>(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) 

Ich verwende das Apache Commons FileUpload Framework für die Verarbeitung von Upload-Anfragen.

Dies geschieht in Firefox und Opera (die einzigen Browser, die ich getestet habe), und während die richtigen Content-Type-Header in Firebug/Developer Console aufgeführt sind, erhält der Server diesen Header nicht (dasselbe gilt für Content-Length-Header) .

Es spielt keine Rolle, ob ich Ajax

jQuery
$.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; 
      } 
     }); 

oder Vanille js

var xhr = new XMLHttpRequest(); 
xhr.upload.onprogress = uploader.uploadProgress; 
xhr.open("POST", "http://host..."); 
xhr.send(formData); 

ich die gleichen Fehler immer. Sobald ich den onprogress-Handler entferne, funktioniert alles gut. Ich habe das schon probiert FormData boundary missing from content-type in POST request header, aber das funktioniert auch nicht für mich.

Weiß jemand, wie man das löst? Vielen Dank!

Edit: Die ajaxData werden aus einem Drop-Ereignis generiert:

var droppedFiles = e.originalEvent.dataTransfer.files; 
    var ajaxData = new FormData(); 
    ajaxData.append("file", droppedFiles[0]); 

Die content: false Option können jQuery/XHR automatisch den Content-Type-Header mit der notwendigen Grenze hinzuzufügen. Diese Option ist erforderlich, ohne sie geht es nicht.

Edit2: Dies funktioniert

$.ajax({ 
      url: "http://host...", 
      type: "POST", 
      data: ajaxData, 
      cache: false, 
      contentType: false, 
      processData: false, 
      xhr: function() { 
       var xhr = jQuery.ajaxSettings.xhr(); 
       return xhr; 
      } 
     }); 

Es scheint nur, dass der Fortschritt Zuhörer Zugabe einen Unterschied macht.

Edit3: Hier ist die serverseitige Code, der den Fehler auslöst:

@Override 
public void handle(HttpExchange httpExchange) throws IOException { 
    DiskFileItemFactory diskFileItemFactory = new DiskFileItemFactory(); 
    ServletFileUpload fileUpload = new ServletFileUpload(diskFileItemFactory); 

    try { 
     List<FileItem> result = fileUpload.parseRequest(new HttpHandlerRequestContext(httpExchange)); 
     (...) 
    } catch (FileUploadException e) { 
     e.printStackTrace(); 
    } 

} 

i https://stackoverflow.com/a/33827895/6655315 diese Antwort folgte. Der HttpHandlerRequestContext entspricht genau dem im verknüpften Post.

Edit4: nur durch einen leeren Upload-Fortschritt-Handler wie diese Zugabe

xhr.upload.onprogress = function(e) {}; 

die empfangenen Header werden von diesem auf diese

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 

Wechsel:

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 
+0

entfernen 'content lesen würde empfehlen: false,' jq sollte den Rest – dandavis

+0

Dank handhaben, aber das funktioniert nicht, da ich bin mit Formdata, für die der Content-Type-Header die Grenze benötigt. Das Entfernen führt zu dem obigen Fehler. – teyzer

+0

Haben Sie jemals herausgefunden, warum der Onprogress Event-Handler die Kopfzeile geändert hat und was der Fix dafür ist? – shreddish

Antwort

0

Sie haben Ihre Antwort in der Ausnahme.

In beiden Beispielen haben Sie den Content-Type-Header nicht so gesetzt, dass er tatsächlich fehlt.

Adding request headers to XHR

jQuery ajax API

ich auch FormData über

+0

Danke für Ihre Antwort. Aber ich benutze bereits FormData (siehe Bearbeiten). Der Content-Type-Header mit boundary include sollte automatisch hinzugefügt werden, dies fehlt jedoch nur bei Verwendung von 'xhr.upload.onprogress' – teyzer

+0

Automatisch von welchem ​​Framework/Spezifikation hinzugefügt? – idan

+0

ist hier angegeben https://www.w3.org/TR/2012/WD-XMLHttpRequest-20120117/#the-send-method im Abschnitt "wenn Daten ein FormData ist". – teyzer