【问题标题】:Apache commons fileupload timeout only with FirefoxApache commons 文件上传超时仅适用于 Firefox
【发布时间】:2019-09-28 07:55:32
【问题描述】:

我在我的 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:版本

没有文件大小限制,好像取决于请求大小,因为解析请求部分太费时间了……

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

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

其实主要的区别是在 Chrome 或者 IE 中,我在请求头中没有上传文件的原始内容:

带有 的部分: 对象 溪流 …… 端流 结束对象

仅在 Firefox 中出现...

【问题讨论】:

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


    【解决方案1】:

    这里有几件事值得一试:

    如果您提供更多信息,例如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?

    【讨论】:

      【解决方案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);
              }
      
              // ...
          }
      

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

      【讨论】:

        【解决方案3】:

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

         request.getSession().setMaxInactiveInterval(1200);
        

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

        【讨论】:

        • 只是延长等待时间,但不解释 6 欧元这么长。
        【解决方案4】:

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

        但是我删除了所有这些,我使用标准输入文件创建了一个新的简单而干净的表单。 我使用来自 ServletFileUpload 的流 API,它可以工作,并且只需几秒钟即可处理大文件。

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

        谢谢!

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2014-06-18
          • 2010-10-23
          • 2010-11-11
          • 2011-01-10
          • 1970-01-01
          • 1970-01-01
          • 2012-12-11
          • 2011-03-26
          相关资源
          最近更新 更多