Opera中基于表单/ iframe的文件上传问题

时间:2011-10-26 06:25:54

标签: java file-upload apache-commons

请参阅下面的答案:issues with form/iframe based file upload in Opera


每当浏览器不支持XMLHttpRequest上传(Opera)时,我都使用表单/ iframe技术将文件发送到服务器。在较高的层面上,这是设置......

  1. 创建iframe <iframe src="javascript:false;" name="file-iframe"></iframe>
  2. 创建表单<form enctype="multipart/form-data" method="POST">
    • 设置target = iframe的名称,target="file-iframe"
    • set action = url,action="/upload"
  3. 将文件输入添加到表单
  4. 提交表格
  5. 提交表单后,服务器会发出异常:

    org.apache.commons.fileupload.MultipartStream$MalformedStreamException: Stream ended unexpectedly
        at org.apache.commons.fileupload.MultipartStream.readHeaders(MultipartStream.java:538)
        at org.apache.commons.fileupload.FileUploadBase$FileItemIteratorImpl.findNextItem(FileUploadBase.java:999)
        at org.apache.commons.fileupload.FileUploadBase$FileItemIteratorImpl.<init>(FileUploadBase.java:965)
        at org.apache.commons.fileupload.FileUploadBase.getItemIterator(FileUploadBase.java:331)
        at org.apache.commons.fileupload.servlet.ServletFileUpload.getItemIterator(ServletFileUpload.java:148)
        at com.beamit.jetty.UploadServlet.doPost(UploadServlet.java:28)
        at javax.servlet.http.HttpServlet.service(HttpServlet.java:727)
        at javax.servlet.http.HttpServlet.service(HttpServlet.java:820)
        ...
        ...
    

    以下是UploadServlet.java文件中的代码段,其中失败发生在代码段的最后一行:

    @Override
    public void doPost(HttpServletRequest request, HttpServletResponse response) {
    
        ServletFileUpload up = new ServletFileUpload();
        try {
            FileItemIterator iter = up.getItemIterator(request); // <------ ERROR
            ...
        } catch (IOException e) {
            e.printStackTrace();
        }
        ...
    

    我一直试图调试这几个小时而且我无处可去。关于为什么会发生这种情况的任何想法?

    我可以使用不同的浏览器提供工作/非工作文件上传的HTTP请求,如果需要还可以提供更多源代码。

    更多信息

    HTTP请求 Chrome 中的简单“hello world”文本文件。

    POST /upload/0145c HTTP/1.1
    Host: beamit:8080
    Connection: keep-alive
    Cache-Control: max-age=0
    User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_7_2) AppleWebKit/535.1 (KHTML, like Gecko) Chrome/14.0.835.202 Safari/535.1
    Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
    Accept-Encoding: gzip,deflate,sdch
    Accept-Language: en-US,en;q=0.8
    Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.3
    Referer: http://beamit:8080/
    Content-Length: 44
    Origin: http://beamit:8080
    Content-Type: multipart/form-data; boundary=----WebKitFormBoundaryQes3eWoFE2iw6kGE
    

    HTTP请求 Opera 中的简单“hello world”文本文件。

    POST /upload/f889b HTTP/1.1
    User-Agent: Opera/9.80 (Macintosh; Intel Mac OS X 10.7.2; U; en) Presto/2.9.168 Version/11.52
    Host: beamit:8080
    Accept: text/html, application/xml;q=0.9, application/xhtml+xml, image/png, image/webp, image/jpeg, image/gif, image/x-xbitmap, */*;q=0.1
    Accept-Language: en,en-US;q=0.9,ja;q=0.8,fr;q=0.7,de;q=0.6,es;q=0.5,it;q=0.4,pt;q=0.3,pt-PT;q=0.2,nl;q=0.1,sv;q=0.1,nb;q=0.1,da;q=0.1,fi;q=0.1,ru;q=0.1,pl;q=0.1,zh-CN;q=0.1,zh-TW;q=0.1,ko;q=0.1,ar;q=0.1,cs;q=0.1,hu;q=0.1,tr;q=0.1
    Accept-Encoding: gzip, deflate
    Referer: http://beamit:8080/
    Cookie: __utma=248039316.1622718495.1317335167.1319648741.1319655028.19; __utmb=248039316.4.10.1319655028; __utmc=248039316; __utmz=248039316.1317335167.1.1.utmcsr=(direct)|utmccn=(direct)|utmcmd=(none)
    Connection: Keep-Alive
    Content-Length: 76
    Content-Type: multipart/form-data; boundary=----------cah2BDOhbumylzxVY398ZJ
    

2 个答案:

答案 0 :(得分:1)

特殊例外表明客户端已中止请求。我不确定确切的原因,但特别是Opera已经知道组合iframe和JavaScript很麻烦。

我强烈建议您抓住一个模拟ajax文件上传作业的现有库,而不是自己重新发明轮子。我在你的问题历史中看到你熟悉jQuery。您可以抓住jQuery form plugin以获得最佳的跨浏览器兼容魔法,如下所示:

<script src="jquery.js"></script>
<script src="jquery.form.js"></script>
<script>
    $(document).ready(function() {
        $('#formid').ajaxForm();
    });
</script>
...
<form id="formid">
    <input type="file" name="file" />
    <input type="submit" />
</form>

您可以根据需要查看jquery.form.js来源here,了解他们如何解决浏览器特定问题。

答案 1 :(得分:1)

我弄清楚问题是什么。在删除所有不必要的代码和标记后,我留下了一个简单的表单/ iframe文件上传页面。

当我动态构建表单时,我将文件输入元素作为子元素插入:

<input type="file" id="file-select-input" />

......我有这样的事情:

<form enctype="multipart/form-data" id="file-select-form" target="select-file-iframe" method="POST" action="/upload/">
    <div id="file-select-button" class="">
        <input type="file" id="file-select-input" />
    </div>
</form>
<iframe style="display: none" id="select-file-iframe" src="javascript:false;" name="select-file-iframe"></iframe>

这个设置给了我这些问题。经过一番调查后发现,当我提交上述表格时,输入的文件信息没有被发送。事实证明,原因是我没有在文件输入元素上指定name属性。所以当我改变它时:

<input type="file" id="file-select-input" name="file" />
事情很有效。