简体   繁体   English

缺少进度侦听器Content-Type标头的FormData文件上传

[英]FormData File Upload with Progress Listener Content-Type header missing

I am building a client-server application with a java-server (no JSP, just com.sun.net.httpserver.HttpServer; ) and web frontend as client. 我正在使用Java服务器(没有JSP,只是com.sun.net.httpserver.HttpServer; )和Web前端作为客户端构建客户端服务器应用程序。 I use WebSockets for communication and want to upload files with XMLHttpRequests and FormData (i followed this post Track ajax post progress for fileupload using jquery ajax and FormData ). 我使用WebSockets进行通信,并希望使用XMLHttpRequests和FormData上载文件(我按照这篇文章使用jquery ajax和FormData跟踪ajax发布文件上传的进度 )。 I want to track the upload progress with xhr.upload.onprogress , but as soon as i add a listener such as 我想用xhr.upload.onprogress跟踪上传进度,但是一旦我添加了一个监听器,例如

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

or 要么

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

i get an serverside error like this: 我收到这样的服务器端错误:

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)

I use the Apache Commons FileUpload framework for handling upload requests. 我使用Apache Commons FileUpload框架来处理上传请求。

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). 这发生在Firefox和Opera(我测试过的唯一浏览器)中,并且在Firebug /开发者控制台中列出了正确的Content-Type标头,但服务器未收到此标头(Content-Length标头也是如此)。

It doesn't matter if i use jQuery ajax 如果我使用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;
           }
       });

or vanilla js 或香草js

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

i always get the same error. 我总是得到同样的错误。 As soon as i remove the onprogress-handler, everything works fine. 一旦我删除了onprogress-handler,一切都会正常。 I already tried this FormData boundary missing from content-type in POST request header , but this doesn't work for me, too. 我已经尝试过POST请求标头中content-type缺少的FormData边界 ,但这对我也不起作用。

Does anybody know how to solve this? 有人知道如何解决这个问题吗? Thank you! 谢谢!

Edit: The ajaxData are generated from an drop event: 编辑:ajaxData是从放置事件生成的:

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

The contentType: false option lets jQuery/XHR automatically add the Content-Type header with the neccessary boundary. contentType:false选项使jQuery / XHR自动添加具有必要边界的Content-Type标头。 This option is required, it doesn't work without it. 此选项是必需的,没有它就无法工作。

Edit2: This works fine Edit2:这很好

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

It seems that only adding the progress listener makes a difference. 似乎仅添加进度侦听器会有所不同。

Edit3: Here is the serverside code that throws the error: 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();
    }

}

i followed this answer https://stackoverflow.com/a/33827895/6655315 . 我按照这个答案https://stackoverflow.com/a/33827895/6655315 The HttpHandlerRequestContext is exactly the same as shown in the linked post. HttpHandlerRequestContext与链接文章中显示的完全相同。

Edit4: just by adding an empty upload progress handler like this Edit4:只需添加一个空的上传进度处理程序,例如

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

the received headers are changing from this 接收到的标头与此不同

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

to this: 对此:

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

You have your answer in the exception. 您有例外的答案。

In both examples you didn't set the Content-Type header so it is indeed missing. 在两个示例中,您都没有设置Content-Type标头,因此确实没有。

Adding request headers to XHR 向XHR添加请求标头

jQuery ajax API jQuery ajax API

I would also recommend reading about FormData 我也建议阅读有关FormData的文章

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM