处理多部分/表单数据请求失败。读取超时

Posted

技术标签:

【中文标题】处理多部分/表单数据请求失败。读取超时【英文标题】:Processing of multipart/form-data request failed. Read timed out 【发布时间】:2012-09-10 16:38:08 【问题描述】:

Stack Overflow 上的其他问题已经解决了这个问题,但所提供的答案都没有帮助我解决这个问题。

我正在尝试使用 Apache HTTP Commons 从小程序上传 10 kB 到 16 MB 之间的文件。在我的本地环境中一切正常。

我仅在我的生产服务器(Tomcat 6.0,https://www.dailyrazor.com/)上收到以下异常,无论文件大小如何:

org.apache.commons.fileupload.FileUploadException: Processing of multipart/form-data request failed. Read timed out
    at org.apache.commons.fileupload.FileUploadBase.parseRequest(FileUploadBase.java:384)
    at org.apache.commons.fileupload.servlet.ServletFileUpload.parseRequest(ServletFileUpload.java:116)
    at com.actura.helper.UploadHelper.processUpload(UploadHelper.java:92)
    at com.actura.voice.upload.FileUploadServlet.process(FileUploadServlet.java:85)
    at com.actura.voice.upload.FileUploadServlet.doPost(FileUploadServlet.java:75)
    at javax.servlet.http.HttpServlet.service(HttpServlet.java:637)
    at javax.servlet.http.HttpServlet.service(HttpServlet.java:717)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:290)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
    at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:233)
    at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:191)
    at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:127)
    at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:102)
    at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:109)
    at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:298)
    at org.apache.jk.server.JkCoyoteHandler.invoke(JkCoyoteHandler.java:190)
    at org.apache.jk.common.HandlerRequest.invoke(HandlerRequest.java:291)
    at org.apache.jk.common.ChannelSocket.invoke(ChannelSocket.java:769)
    at org.apache.jk.common.ChannelSocket.processConnection(ChannelSocket.java:698)
    at org.apache.jk.common.ChannelSocket$SocketConnection.runIt(ChannelSocket.java:891)
    at org.apache.tomcat.util.threads.ThreadPool$ControlRunnable.run(ThreadPool.java:690)
    at java.lang.Thread.run(Thread.java:662)

这是Commons IO的调试日志:

2012-Sep-18 11:26:28,446 [TP-Processor5] com.actura.voice.upload.MonitoredDiskFileItemFactory 
  DEBUG inside MonitoredDiskFileItemFactory constructor (listener) 
2012-Sep-18 11:26:28,794 [TP-Processor5] com.actura.voice.upload.MonitoredDiskFileItemFactory 
  DEBUG inside MonitoredDiskFileItemFactory createItem 
2012-Sep-18 11:26:28,800 [TP-Processor5] com.actura.voice.upload.MonitoredDiskFileItem 
  DEBUG inside MonitoredDiskFileItem constructor 
2012-Sep-18 11:26:28,800 [TP-Processor5] com.actura.voice.upload.MonitoredDiskFileItem 
  DEBUG inside getOutputStream() 
2012-Sep-18 11:26:28,802 [TP-Processor5] com.actura.voice.upload.MonitoredOutputStream 
  DEBUG inside MonitoredOutputStream constructor 
2012-Sep-18 11:26:28,803 [TP-Processor5] com.actura.voice.upload.MonitoredOutputStream 
  DEBUG leaving MonitoredOutputStream contructor 
2012-Sep-18 11:26:28,803 [TP-Processor5] com.actura.voice.upload.MonitoredDiskFileItem 
  DEBUG leaving getOutputStream() 
2012-Sep-18 11:26:28,803 [TP-Processor5] com.actura.voice.upload.MonitoredDiskFileItemFactory 
  DEBUG inside MonitoredDiskFileItemFactory createItem 
2012-Sep-18 11:26:28,803 [TP-Processor5] com.actura.voice.upload.MonitoredDiskFileItem 
  DEBUG inside MonitoredDiskFileItem constructor 
2012-Sep-18 11:26:28,803 [TP-Processor5] com.actura.voice.upload.MonitoredDiskFileItem 
  DEBUG inside getOutputStream() 
2012-Sep-18 11:26:28,803 [TP-Processor5] com.actura.voice.upload.MonitoredOutputStream 
  DEBUG inside MonitoredOutputStream constructor 
2012-Sep-18 11:26:28,803 [TP-Processor5] com.actura.voice.upload.MonitoredOutputStream 
  DEBUG leaving MonitoredOutputStream contructor 
2012-Sep-18 11:26:28,803 [TP-Processor5] com.actura.voice.upload.MonitoredDiskFileItem 
  DEBUG leaving getOutputStream() 
2012-Sep-18 11:26:28,803 [TP-Processor5] com.actura.voice.upload.MonitoredDiskFileItemFactory 
  DEBUG inside MonitoredDiskFileItemFactory createItem 
2012-Sep-18 11:26:28,803 [TP-Processor5] com.actura.voice.upload.MonitoredDiskFileItem 
  DEBUG inside MonitoredDiskFileItem constructor 
2012-Sep-18 11:26:28,803 [TP-Processor5] com.actura.voice.upload.MonitoredDiskFileItem 
  DEBUG inside getOutputStream() 
2012-Sep-18 11:26:28,803 [TP-Processor5] com.actura.voice.upload.MonitoredOutputStream 
  DEBUG inside MonitoredOutputStream constructor 
2012-Sep-18 11:26:28,803 [TP-Processor5] com.actura.voice.upload.MonitoredOutputStream 
  DEBUG leaving MonitoredOutputStream contructor 
2012-Sep-18 11:26:28,804 [TP-Processor5] com.actura.voice.upload.MonitoredDiskFileItem 
  DEBUG leaving getOutputStream() 
2012-Sep-18 11:26:28,804 [TP-Processor5] com.actura.voice.upload.MonitoredDiskFileItemFactory 
  DEBUG inside MonitoredDiskFileItemFactory createItem 
2012-Sep-18 11:26:28,804 [TP-Processor5] com.actura.voice.upload.MonitoredDiskFileItem 
  DEBUG inside MonitoredDiskFileItem constructor 
2012-Sep-18 11:26:28,804 [TP-Processor5] com.actura.voice.upload.MonitoredDiskFileItem 
  DEBUG inside getOutputStream() 
2012-Sep-18 11:26:28,804 [TP-Processor5] com.actura.voice.upload.MonitoredOutputStream 
  DEBUG inside MonitoredOutputStream constructor 
2012-Sep-18 11:26:28,804 [TP-Processor5] com.actura.voice.upload.MonitoredOutputStream 
  DEBUG leaving MonitoredOutputStream contructor 
2012-Sep-18 11:26:28,804 [TP-Processor5] com.actura.voice.upload.MonitoredDiskFileItem 
  DEBUG leaving getOutputStream() 
 processing folder... /home/dixieh83/public_html/ActuraVoiceRecorderDemo/temp
2012-Sep-18 11:27:47,062 [TP-Processor4] com.actura.voice.upload.MonitoredDiskFileItemFactory 
  DEBUG inside MonitoredDiskFileItemFactory constructor (listener) 
2012-Sep-18 11:27:47,461 [TP-Processor4] com.actura.voice.upload.MonitoredDiskFileItemFactory 
  DEBUG inside MonitoredDiskFileItemFactory createItem 
2012-Sep-18 11:27:47,461 [TP-Processor4] com.actura.voice.upload.MonitoredDiskFileItem 
  DEBUG inside MonitoredDiskFileItem constructor 
2012-Sep-18 11:27:47,462 [TP-Processor4] com.actura.voice.upload.MonitoredDiskFileItem 
  DEBUG inside getOutputStream() 
2012-Sep-18 11:27:47,462 [TP-Processor4] com.actura.voice.upload.MonitoredOutputStream 
  DEBUG inside MonitoredOutputStream constructor 
2012-Sep-18 11:27:47,462 [TP-Processor4] com.actura.voice.upload.MonitoredOutputStream 
  DEBUG leaving MonitoredOutputStream contructor 
2012-Sep-18 11:27:47,462 [TP-Processor4] com.actura.voice.upload.MonitoredDiskFileItem 
  DEBUG leaving getOutputStream() 
2012-Sep-18 11:27:47,462 [TP-Processor4] com.actura.voice.upload.MonitoredDiskFileItemFactory 
  DEBUG inside MonitoredDiskFileItemFactory createItem 
2012-Sep-18 11:27:47,462 [TP-Processor4] com.actura.voice.upload.MonitoredDiskFileItem 
  DEBUG inside MonitoredDiskFileItem constructor 
2012-Sep-18 11:27:47,462 [TP-Processor4] com.actura.voice.upload.MonitoredDiskFileItem 
  DEBUG inside getOutputStream() 
2012-Sep-18 11:27:47,462 [TP-Processor4] com.actura.voice.upload.MonitoredOutputStream 
  DEBUG inside MonitoredOutputStream constructor 
2012-Sep-18 11:27:47,462 [TP-Processor4] com.actura.voice.upload.MonitoredOutputStream 
  DEBUG leaving MonitoredOutputStream contructor 
2012-Sep-18 11:27:47,462 [TP-Processor4] com.actura.voice.upload.MonitoredDiskFileItem 
  DEBUG leaving getOutputStream() 
2012-Sep-18 11:27:47,463 [TP-Processor4] com.actura.voice.upload.MonitoredDiskFileItemFactory 
  DEBUG inside MonitoredDiskFileItemFactory createItem 
2012-Sep-18 11:27:47,463 [TP-Processor4] com.actura.voice.upload.MonitoredDiskFileItem 
  DEBUG inside MonitoredDiskFileItem constructor 
2012-Sep-18 11:27:47,463 [TP-Processor4] com.actura.voice.upload.MonitoredDiskFileItem 
  DEBUG inside getOutputStream() 
2012-Sep-18 11:27:47,463 [TP-Processor4] com.actura.voice.upload.MonitoredOutputStream 
  DEBUG inside MonitoredOutputStream constructor 
2012-Sep-18 11:27:47,463 [TP-Processor4] com.actura.voice.upload.MonitoredOutputStream 
  DEBUG leaving MonitoredOutputStream contructor 
2012-Sep-18 11:27:47,463 [TP-Processor4] com.actura.voice.upload.MonitoredDiskFileItem 
  DEBUG leaving getOutputStream() 
2012-Sep-18 11:27:47,463 [TP-Processor4] com.actura.voice.upload.MonitoredDiskFileItemFactory 
  DEBUG inside MonitoredDiskFileItemFactory createItem 
2012-Sep-18 11:27:47,463 [TP-Processor4] com.actura.voice.upload.MonitoredDiskFileItem 
  DEBUG inside MonitoredDiskFileItem constructor 
2012-Sep-18 11:27:47,463 [TP-Processor4] com.actura.voice.upload.MonitoredDiskFileItem 
  DEBUG inside getOutputStream() 
2012-Sep-18 11:27:47,463 [TP-Processor4] com.actura.voice.upload.MonitoredOutputStream 
  DEBUG inside MonitoredOutputStream constructor 
2012-Sep-18 11:27:47,463 [TP-Processor4] com.actura.voice.upload.MonitoredOutputStream 
  DEBUG leaving MonitoredOutputStream contructor 
2012-Sep-18 11:27:47,463 [TP-Processor4] com.actura.voice.upload.MonitoredDiskFileItem 
  DEBUG leaving getOutputStream() 

除了这个上传问题,我的小程序工作正常。

这是我的生产服务器的server.xml 文件中描述的服务器配置:

<!-- Define an AJP 1.3 Connector on port 8009 --> <Connector address="127.0.0.1" port="9609" enableLookups="false" protocol="AJP/1.3" connectionTimeout="30000" maxThreads="50" minSpareThreads="1" maxSpareThreads="3" disableUploadTimeout="true" /> 

我的互联网连接速度很好(下行 2.01 Mbps,上行 0.42 Mbps),所以这个例外让我感到困惑。我已经将connectionTimeOut 设置为 3000000,但我仍然遇到异常。我应该将connectionTimeOut 设置为-1 以使其不受限制吗?

我上传的目录上的文件权限设置为777,并且我使用JDK 7 在浏览器中运行小程序。

Java 控制台输出:

Java Plug-in 10.7.2.10
Using JRE version 1.7.0_07-b10 Java HotSpot(TM) Client VM

当上传失败时,我在控制台中得到这个:

java.net.SocketException: Connection reset by peer: socket write error
    at java.net.SocketOutputStream.socketWrite0(Native Method)
    at java.net.SocketOutputStream.socketWrite(Unknown Source)
    at java.net.SocketOutputStream.write(Unknown Source)
    at org.apache.http.impl.io.AbstractSessionOutputBuffer.write(AbstractSessionOutputBuffer.java:169)
    at org.apache.http.impl.io.ContentLengthOutputStream.write(ContentLengthOutputStream.java:119)
    at org.apache.http.entity.mime.content.InputStreamBody.writeTo(InputStreamBody.java:70)
    at org.apache.http.entity.mime.HttpMultipart.doWriteTo(HttpMultipart.java:206)
    at org.apache.http.entity.mime.HttpMultipart.writeTo(HttpMultipart.java:224)
    at org.apache.http.entity.mime.MultipartEntity.writeTo(MultipartEntity.java:183)
    at org.apache.http.entity.HttpEntityWrapper.writeTo(HttpEntityWrapper.java:98)
    at org.apache.http.impl.client.EntityEnclosingRequestWrapper$EntityWrapper.writeTo(EntityEnclosingRequestWrapper.java:108)
    at org.apache.http.impl.entity.EntitySerializer.serialize(EntitySerializer.java:122)
    at org.apache.http.impl.AbstractHttpClientConnection.sendRequestEntity(AbstractHttpClientConnection.java:271)
    at org.apache.http.impl.conn.ManagedClientConnectionImpl.sendRequestEntity(ManagedClientConnectionImpl.java:197)
    at org.apache.http.protocol.HttpRequestExecutor.doSendRequest(HttpRequestExecutor.java:257)
    at org.apache.http.protocol.HttpRequestExecutor.execute(HttpRequestExecutor.java:125)
    at org.apache.http.impl.client.DefaultRequestDirector.tryExecute(DefaultRequestDirector.java:712)
    at org.apache.http.impl.client.DefaultRequestDirector.execute(DefaultRequestDirector.java:517)
    at org.apache.http.impl.client.AbstractHttpClient.execute(AbstractHttpClient.java:906)
    at org.apache.http.impl.client.AbstractHttpClient.execute(AbstractHttpClient.java:1066)
    at org.apache.http.impl.client.AbstractHttpClient.execute(AbstractHttpClient.java:1044)
    at org.apache.http.impl.client.AbstractHttpClient.execute(AbstractHttpClient.java:1035)
    at com.actura.app.util.ApplicationUtil.uploadUsingApache(ApplicationUtil.java:143)
    at com.actura.app.util.ApplicationUtil.saveWaveToServer(ApplicationUtil.java:90)
    at com.actura.app.capture.RecorderUI.saveButtonActionPerformed(RecorderUI.java:1856)
    at com.actura.app.capture.RecorderUI.access$17(RecorderUI.java:1824)
    at com.actura.app.capture.RecorderUI$7.actionPerformed(RecorderUI.java:1325)
    at javax.swing.AbstractButton.fireActionPerformed(Unknown Source)
    at javax.swing.AbstractButton$Handler.actionPerformed(Unknown Source)
    at javax.swing.DefaultButtonModel.fireActionPerformed(Unknown Source)
    at javax.swing.DefaultButtonModel.setPressed(Unknown Source)
    at javax.swing.plaf.basic.BasicButtonListener.mouseReleased(Unknown Source)
    at java.awt.Component.processMouseEvent(Unknown Source)
    at javax.swing.JComponent.processMouseEvent(Unknown Source)
    at java.awt.Component.processEvent(Unknown Source)
    at java.awt.Container.processEvent(Unknown Source)
    at java.awt.Component.dispatchEventImpl(Unknown Source)
    at java.awt.Container.dispatchEventImpl(Unknown Source)
    at java.awt.Component.dispatchEvent(Unknown Source)
    at java.awt.LightweightDispatcher.retargetMouseEvent(Unknown Source)
    at java.awt.LightweightDispatcher.processMouseEvent(Unknown Source)
    at java.awt.LightweightDispatcher.dispatchEvent(Unknown Source)
    at java.awt.Container.dispatchEventImpl(Unknown Source)
    at java.awt.Component.dispatchEvent(Unknown Source)
    at java.awt.EventQueue.dispatchEventImpl(Unknown Source)
    at java.awt.EventQueue.access$200(Unknown Source)
    at java.awt.EventQueue$3.run(Unknown Source)
    at java.awt.EventQueue$3.run(Unknown Source)
    at java.security.AccessController.doPrivileged(Native Method)
    at java.security.ProtectionDomain$1.doIntersectionPrivilege(Unknown Source)
    at java.security.ProtectionDomain$1.doIntersectionPrivilege(Unknown Source)
    at java.awt.EventQueue$4.run(Unknown Source)
    at java.awt.EventQueue$4.run(Unknown Source)
    at java.security.AccessController.doPrivileged(Native Method)
    at java.security.ProtectionDomain$1.doIntersectionPrivilege(Unknown Source)
    at java.awt.EventQueue.dispatchEvent(Unknown Source)
    at java.awt.EventDispatchThread.pumpOneEventForFilters(Unknown Source)
    at java.awt.EventDispatchThread.pumpEventsForFilter(Unknown Source)
    at java.awt.EventDispatchThread.pumpEventsForHierarchy(Unknown Source)
    at java.awt.EventDispatchThread.pumpEvents(Unknown Source)
    at java.awt.EventDispatchThread.pumpEvents(Unknown Source)
    at java.awt.EventDispatchThread.run(Unknown Source)

我知道这可能是我的 ISP 的问题。我只是想知道是不是iSP的问题,为什么我可以流畅地使用temviewer和Skype之类的软件??

以下是执行上传的代码:

public static String uploadUsingApache(URL url, List<File> list,
            String userId, String accountId, String waveDuration)
            throws Exception 

        // The execution:
        DefaultHttpClient httpclient = new DefaultHttpClient();

        HttpPost method = new HttpPost(url.toString());

        MultipartEntity entity = new MultipartEntity();
        entity.addPart("userId", new StringBody(userId, Charset
                .forName("UTF-8")));
        entity.addPart(IVR_ACCOUNT_KEY, new StringBody(accountId, Charset
                .forName("UTF-8")));
        entity.addPart(IVR_MP3LEN_KEY, new StringBody(waveDuration, Charset
                .forName("UTF-8")));

        // FileBody fileBody = new FileBody(list.get(0));
        // entity.addPart("file", fileBody);

        for (File f : list) 

            byte[] imageBytes = fileToByteArray(f);
            entity.addPart("attachment_field", new InputStreamKnownSizeBody(
                    new ByteArrayInputStream(imageBytes), imageBytes.length,
                    "audio/wav", f.getName()));
            method.setEntity(entity);
        

        ResponseHandler<String> responseHandler = new BasicResponseHandler();

        // HttpResponse response = httpclient.execute(method,responseHandler);
        String responseText = httpclient.execute(method, responseHandler);

        // error text
        if (responseText.contains("<exception>")) 
            responseText = responseText.replace("<exception>", "");
            responseText = responseText.replace("</exception>", "");
            throw new Exception(responseText);
        

        // System.out.println(" Status " +response.getStatusLine());
        List<String> deleteList = Arrays.asList(responseText.split(","));

        StringBuffer sb = new StringBuffer();
        int cnt = 1;
        for (File f : list) 
            if (deleteList.contains(f.getName())) 
                sb.append(f.getName() + (cnt == deleteList.size() ? "" : ", "));
                f.delete();
                cnt++;
            

        

        if (deleteList.size() > 1) 
            sb.append(" are ");
         else if (deleteList.size() == 1) 
            sb.append(" is ");
         else 

        

        sb.append(" successfully saved.");

        return sb.toString();
    

当我按下小程序 GUI 上的上传按钮时,它会调用上述方法,同时 GUI 会冻结。 10 到 50 秒后,服务器抛出 FileUploadException。 servlet 将异常通知小程序,但小程序在通知用户异常之前挂起四五分钟。

如果服务器端出现问题,为什么会有这么多延迟?

【问题讨论】:

如果您链接到您已经看到发布的类似问题会很有帮助,特别是如果您详细说明您已经尝试过哪些步骤,为什么它们不起作用您,以及您的环境与该解决方案有效的环境有何不同。 您在浏览器中运行小程序的 Java 版本是什么?除了此上传功能之外,小程序是否可以正常加载和工作? 是的,我正在使用 Jdk 7 来运行小程序。除了这个上传功能之外,小程序工作正常。上传速度有问题吗?? 【参考方案1】:

这对我帮助很大:http://blog.somepixels.net/en/502-proxy-error-uploading-from-apache-mod_proxy-to-tomcat-7/

基本上在我的 server.xml 中我将其设置为:

<Connector port="8080" protocol="HTTP/1.1" URIEncoding="UTF-8"
       connectionUploadTimeout="36000000" disableUploadTimeout="false"
       connectionTimeout="60000" redirectPort="8443" />

【讨论】:

[connectionUploadTimeout]:指定在数据上传过程中使用的超时时间,以毫秒为单位。这仅在 disableUploadTimeout 设置为 false 时生效。 [disableUploadTimeout]:此标志允许 servlet 容器在数据上传期间使用不同的、通常更长的连接超时。如果未指定,则此属性设置为 true 以禁用此更长的超时。 [来源]:tomcat.apache.org/tomcat-7.0-doc/config/http.html【参考方案2】:

从问题中不清楚您正在运行什么配置(或者您已经尝试过什么),但问题几乎是根据定义,在上传期间超过了套接字超时。

由于在达到相关超时之前未完全接收文件,因此引发错误。这与在测试中(在本地网络上)工作的情况一致,但在运行速度较慢的互联网时(尤其是在上传速度方面)则不然。

查看您的 server.xml 以了解相关的 &lt;Connector&gt; 定义。您将对connectionTimeoutconnectionUploadTimeout 属性的值感兴趣(如果disableUploadTimeout 设置为true,则为后者)。

在没有更严重问题的证据的情况下,我希望您可以通过增加连接超时来解决此问题。

【讨论】:

这是我从生产服务器的 server.xml 复制的 xml。 我的网速也很好,我不明白生产服务器有什么问题,我应该将connectionTimeOut设置为-1以使其无限制吗?? 我刚刚使用 speedtest.com 检查了我的速度,结果是下载速度为 2.01 mbps,上传速度为 0.42 mbps 我已将 connectionTimeout 设置为 3000000 但同样的例外。我怎样才能摆脱这个?

以上是关于处理多部分/表单数据请求失败。读取超时的主要内容,如果未能解决你的问题,请参考以下文章

多部分/表单数据请求在 react-native 中失败

如何在没有快递的情况下处理多部分/表单数据请求

PHP多部分表单数据PUT请求?

解析Servlet中传入的多部分/表单数据参数的便捷方法[重复]

Nodejs POST 请求多部分/表单数据

解析多部分/表单数据,从请求后接收