Apache Commons文件上传超时仅适用于Firefox

时间:2019-05-10 11:44:36

标签: http servlets upload request apache-commons-fileupload

我在我的Java项目中使用Apache commons fileupload 1.4库。 我有一个具有经典形式的html部分,带有文件输入和一些隐藏字段。

我仅使用Firefox> = 52上载> 500ko左右的文件时遇到问题

它与Chrome或Internet Explorer中10mo的文件兼容。 但是,使用Firefox,我在提交表单后等待了几分钟才超时。

经过一些调试,我发现造成超时的代码是:

List<FileItem> items = (new ServletFileUpload(new DiskFileItemFactory())).parseRequest(request);

有原因等待的部分是“ parseRequest”。

我尝试使用IntelliJ中的调试器调试请求的内容,但是无法以原始格式复制此请求对象的整个内容值。

在以下情况下有效: -Firefox:版本<= 52或文件大小<500ko(大约不是很精确) - IE浏览器 -Chrome

没有文件大小限制,这似乎取决于请求的大小,因为解析请求部分花费了太多时间...

在两种情况下,我都收到了带有Firefox扩展名的HTTP请求。 一个生成的文件上传失败的3mo文件(请求文件很大,是上传文件大小的3倍): https://code.empreintesduweb.com/13561.html

一个生成的上传文件200ko有效(请求文件很小): https://code.empreintesduweb.com/13560.html

实际上,主要区别在于在Chrome或IE中,请求标头中没有上传文件的原始内容:

具有的部分: 对象 流 .... 尾流 endobj

仅在Firefox中显示...

4 个答案:

答案 0 :(得分:2)

一些值得在这里尝试的事情:

如果您提供更多信息(例如apache / java / servlet的版本)以及更多代码(尤其是request的定义),我们也可能会更好地帮助您

  

一些有用的资源:
  XMLHttpRequest
  Sending_files_using_a_FormData_object
  How to set a header for a HTTP GET request, and trigger file download?

答案 1 :(得分:2)

您可以尝试设置最大文件大小,也许文件大小超过了最大阈值。根据documentation

  
      
  • 上载的项目应保留在内存中,只要它们很小即可。
  •   
  • 较大的项目应写入磁盘上的临时文件中。
  •   
  • 不允许很大的上传请求。
  •   
  • 内置默认设置为要保留在内存中的最大项目大小,允许的最大上传大小   请求,并且可以接受临时文件的位置。
  •   

尝试以下方法:

 protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        try {
            // Set factory constraints
           DiskFileItemFactory factory = new DiskFileItemFactory();
           factory.setSizeThreshold(yourMaxMemorySize);
           ServletContext servletContext = this.getServletConfig().getServletContext();
           File repository = (File) servletContext.getAttribute("javax.servlet.context.tempdir");
           factory.setRepository(repository);
            List<FileItem> items = new ServletFileUpload(factory).parseRequest(request);
            for (FileItem item : items) {
                if (item.isFormField()) {
                    // Process regular form field (input type="text|radio|checkbox|etc", select, etc).
                    String fieldName = item.getFieldName();
                    String fieldValue = item.getString();
                    // ... (do your job here)
                } else {
                    // Process form file field (input type="file").
                    String fieldName = item.getFieldName();
                    String fileName = FilenameUtils.getName(item.getName());
                    InputStream fileContent = item.getInputStream();
                    // ... (do your job here)
                }
            }
        } catch (FileUploadException e) {
            throw new ServletException("Cannot parse multipart request.", e);
        }

        // ...
    }

在这里,由于文件很大,我们正在为文件提供临时位置。

答案 2 :(得分:0)

尝试使用setMaxInactiveInterval方法设置会话超时

 request.getSession().setMaxInactiveInterval(1200);
  

参数指定客户端请求之前到请求之间的时间(以秒为单位)   Servlet容器将使该会话无效。间隔值   零或更少表示会话永不超时。

答案 3 :(得分:0)

感谢您的所有回答。 最后,我成功解决了这个问题,但实际上...并非如此。 我注意到表格中有一些特定的内容。 我有两个输入,一个是标准文件输入,另一个是在任何上传之前接收一些奇怪的js在base64中编码的文件内容。 所以我只有一次文件的原始内容,还有base64中的文件。为什么呢?我不知道。

但是我删除了所有这些,我创建了一个带有标准输入文件的新的简洁表格。 我使用的是ServletFileUpload中的流API,它可以正常工作,大文件只需几秒钟。

所以我不了解所有内容(例如,为什么问题只在某些浏览器上出现),但是我找到了解决方法;)

谢谢!