FormData文件上载时缺少Progress Listener Content-Type标头

时间:2016-07-29 17:25:23

标签: javascript java jquery ajax file-upload

我正在使用java-server(没有JSP,只有com.sun.net.httpserver.HttpServer;)和web前端作为客户端构建客户端 - 服务器应用程序。我使用WebSockets进行通信,并希望使用XMLHttpRequests和FormData上传文件(我跟着这篇文章Track ajax post progress for fileupload using jquery ajax and FormData)。我希望使用xhr.upload.onprogress跟踪上传进度,但只要添加一个监听器,例如

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

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

我收到像这样的服务器端错误:

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)

我使用Apache Commons FileUpload框架来处理上传请求。

这发生在Firefox和Opera(我测试的唯一浏览器)中,虽然Firebug /开发者控制台中列出了正确的Content-Type标头,但服务器不会收到此标头(Content-Length标头也是如此)。

如果我使用jQuery ajax

并不重要
$.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;
           }
       });

或vanilla js

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

我总是得到同样的错误。 一旦我删除onprogress-handler,一切正常。 我已经尝试了这个FormData boundary missing from content-type in POST request header,但这对我也不起作用。

有人知道如何解决这个问题吗? 谢谢!

编辑: ajaxData是从drop事件生成的:

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

contentType:false选项允许jQuery / XHR自动添加带有必要边界的Content-Type标头。此选项是必需的,没有它就无法使用。

EDIT2: 这很好用

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

似乎只添加进度监听器才有所作为。

EDIT3: 以下是抛出错误的服务器端代码:

@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();
    }

}

我按照这个回答https://stackoverflow.com/a/33827895/6655315。 HttpHandlerRequestContext与链接帖子中显示的完全相同。

Edit4: 只需添加一个像这样的空上传进度处理程序

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

收到的标题正在从此更改

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

到此:

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

1 个答案:

答案 0 :(得分:0)

你有异常的答案。

在这两个示例中,您都没有设置Content-Type标头,因此确实缺少它。

Adding request headers to XHR

jQuery ajax API

我还建议您阅读FormData