春季3上传文件问题 - MultipartException,连接重置

时间:2012-10-24 13:31:09

标签: spring file-upload multipart

我有一个属于Web应用程序的表单,其中包含一个“文件”字段来上传pdf文件。(spring 3环境,多部分文件上传) 上传文件在测试环境(所有浏览器)中都能正常工作,并且只适用于生产环境中的Firefox(文件上传导致连接重置异常,特别是低互联网连接客户端浏览器)

按下提交按钮几秒后抛出以下异常:(浏览器是在Windows环境中运行的IE / Chrome,但不是Firefox)

org.springframework.web.multipart.MultipartException: Could not parse multipart servlet request; nested exception is org.apache.commons.fileupload.FileUploadBase$IOFileUploadException: Processing of multipart/form-data request failed. null
    at org.springframework.web.multipart.commons.CommonsMultipartResolver.parseRequest(CommonsMultipartResolver.java:162)
    at org.springframework.web.multipart.commons.CommonsMultipartResolver.resolveMultipart(CommonsMultipartResolver.java:138)
    at org.springframework.web.servlet.DispatcherServlet.checkMultipart(DispatcherServlet.java:887)
    at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:750)
    at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:719)
    at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:644)
    at org.springframework.web.servlet.FrameworkServlet.doPost(FrameworkServlet.java:560)
    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.springframework.security.web.FilterChainProxy.doFilter(FilterChainProxy.java:162)
    at org.springframework.web.filter.DelegatingFilterProxy.invokeDelegate(DelegatingFilterProxy.java:237)
    at org.springframework.web.filter.DelegatingFilterProxy.doFilter(DelegatingFilterProxy.java:167)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:235)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
    at org.jasig.cas.client.session.SingleSignOutFilter.doFilter(SingleSignOutFilter.java:110)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:235)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
    at fr.ifma.utils.FiltreUTF8.doFilter(FiltreUTF8.java:21)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:235)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
    at org.springframework.orm.hibernate3.support.OpenSessionInViewFilter.doFilterInternal(OpenSessionInViewFilter.java:198)
    at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:76)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:235)
    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:293)
    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:776)
    at org.apache.jk.common.ChannelSocket.processConnection(ChannelSocket.java:705)
    at org.apache.jk.common.ChannelSocket$SocketConnection.runIt(ChannelSocket.java:898)
    at org.apache.tomcat.util.threads.ThreadPool$ControlRunnable.run(ThreadPool.java:690)
    at java.lang.Thread.run(Thread.java:662)
Caused by: org.apache.commons.fileupload.FileUploadBase$IOFileUploadException: Processing of multipart/form-data request failed. null
    at org.apache.commons.fileupload.FileUploadBase.parseRequest(FileUploadBase.java:371)
    at org.apache.commons.fileupload.servlet.ServletFileUpload.parseRequest(ServletFileUpload.java:126)
    at org.springframework.web.multipart.commons.CommonsMultipartResolver.parseRequest(CommonsMultipartResolver.java:155)
    ... 38 more
Caused by: java.io.IOException
    at org.apache.jk.common.JkInputStream.receive(JkInputStream.java:205)
    at org.apache.jk.common.JkInputStream.refillReadBuffer(JkInputStream.java:265)
    at org.apache.jk.common.JkInputStream.doRead(JkInputStream.java:183)
    at org.apache.coyote.Request.doRead(Request.java:427)
    at org.apache.catalina.connector.InputBuffer.realReadBytes(InputBuffer.java:304)
    at org.apache.tomcat.util.buf.ByteChunk.substract(ByteChunk.java:419)
    at org.apache.catalina.connector.InputBuffer.read(InputBuffer.java:327)
    at org.apache.catalina.connector.CoyoteInputStream.read(CoyoteInputStream.java:193)
    at org.apache.commons.fileupload.MultipartStream$ItemInputStream.makeAvailable(MultipartStream.java:976)
    at org.apache.commons.fileupload.MultipartStream$ItemInputStream.read(MultipartStream.java:886)
    at java.io.InputStream.read(InputStream.java:82)
    at org.apache.commons.fileupload.util.Streams.copy(Streams.java:96)
    at org.apache.commons.fileupload.util.Streams.copy(Streams.java:66)
    at org.apache.commons.fileupload.FileUploadBase.parseRequest(FileUploadBase.java:366)
    ... 40 more
24 oct. 2012 10:40:38 org.apache.jk.core.MsgContext action
ATTENTION: Unable to send headers
java.net.SocketException: Broken pipe
    at java.net.SocketOutputStream.socketWrite0(Native Method)
    at java.net.SocketOutputStream.socketWrite(SocketOutputStream.java:92)
    at java.net.SocketOutputStream.write(SocketOutputStream.java:136)
    at org.apache.jk.common.ChannelSocket.send(ChannelSocket.java:539)
    at org.apache.jk.common.JkInputStream.appendHead(JkInputStream.java:324)
    at org.apache.jk.core.MsgContext.action(MsgContext.java:266)
    at org.apache.coyote.Response.action(Response.java:183)
    at org.apache.coyote.Response.sendHeaders(Response.java:379)
    at org.apache.catalina.connector.OutputBuffer.doFlush(OutputBuffer.java:314)
    at org.apache.catalina.connector.OutputBuffer.close(OutputBuffer.java:274)
    at org.apache.catalina.connector.CoyoteWriter.close(CoyoteWriter.java:108)
    at org.apache.catalina.core.ApplicationDispatcher.doForward(ApplicationDispatcher.java:394)
    at org.apache.catalina.core.ApplicationDispatcher.forward(ApplicationDispatcher.java:302)
    at org.springframework.web.servlet.view.InternalResourceView.renderMergedOutputModel(InternalResourceView.java:238)
    at org.springframework.web.servlet.view.AbstractView.render(AbstractView.java:250)
    at org.springframework.web.servlet.DispatcherServlet.render(DispatcherServlet.java:1047)
    at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:817)
    at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:719)
    at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:644)
    at org.springframework.web.servlet.FrameworkServlet.doPost(FrameworkServlet.java:560)
    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.springframework.security.web.FilterChainProxy.doFilter(FilterChainProxy.java:162)
    at org.springframework.web.filter.DelegatingFilterProxy.invokeDelegate(DelegatingFilterProxy.java:237)
    at org.springframework.web.filter.DelegatingFilterProxy.doFilter(DelegatingFilterProxy.java:167)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:235)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
    at org.jasig.cas.client.session.SingleSignOutFilter.doFilter(SingleSignOutFilter.java:110)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:235)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
    at fr.ifma.utils.FiltreUTF8.doFilter(FiltreUTF8.java:21)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:235)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
    at org.springframework.orm.hibernate3.support.OpenSessionInViewFilter.doFilterInternal(OpenSessionInViewFilter.java:198)
    at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:76)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:235)
    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:293)
    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:776)
    at org.apache.jk.common.ChannelSocket.processConnection(ChannelSocket.java:705)
    at org.apache.jk.common.ChannelSocket$SocketConnection.runIt(ChannelSocket.java:898)
    at org.apache.tomcat.util.threads.ThreadPool$ControlRunnable.run(ThreadPool.java:690)
    at java.lang.Thread.run(Thread.java:662)
24 oct. 2012 10:40:38 org.apache.jk.common.ChannelSocket processConnection

以下是网络应用程序代码和配置:

spring multipart resolver配置:                            

控制器:

/**      
 * this controller handles file upload and save files to dao.
     * @author Christophe.Dumonet@ifma.fr
     * @param request
 * @param documentFormBean
 * @param result
 * @param file
 * @return
 */
@RequestMapping(value = "/save", method = RequestMethod.POST)
public ModelAndView save(HttpServletRequest request,
        @Valid DocumentFormBean documentFormBean,BindingResult result,
        @RequestParam("file") MultipartFile file) {
    ResourceBundle bundle = ResourceBundle.getBundle("messages", request.getLocale());

    Map<String,Object> map = new HashMap<String, Object>();

    map.put("documentFormBean", new DocumentFormBean());
    map.put("documentList", documentDao.findAllForaDepot(Long.parseLong((String) request.getParameter("depot"))));
    map.put("depot", depotDao.find(Long.parseLong((String) request.getParameter("depot"))));

    //Handle too many documents attached : how many documents attached to this depot now ? throw an error to UI.
    @SuppressWarnings("rawtypes")
    List documentAttached = documentDao.findAllForaDepot(Long.parseLong((String) request.getParameter("depot")));
    if (documentAttached != null && documentAttached.size() >= Integer.parseInt(SpringPropertiesUtil.getProperty("Depot.maximum.file.number.authorized"))){
        map.put("MaximumFileNumberReached", bundle.getString("Depot.maximum.file.number.errormessage"));
        return new ModelAndView("ajoutDocumentsRapport", map);
    }

    //handle file empty or not pdf
    if (result.hasErrors() || (file.isEmpty()) || !file.getContentType().contains("pdf")) {
        map.put("errors", result);

        if (file.isEmpty()) map.put("ErrorMessageFileEmpty", bundle.getString("view.addrapport.error.fileisempty"));

        if (!file.getContentType().contains("pdf")) map.put("ErrorMessageFileTypeNotPDF", bundle.getString("view.addrapport.error.filetype.onlypdf"));
        return new ModelAndView("ajoutDocumentsRapport", map);
    } else{


    try {
        //Blob blob = Hibernate.createBlob(file.getInputStream());
        //cause Hibernate.createBlob is deprecated, use a LobHelper interface instead.
        org.hibernate.Session se = (org.hibernate.Session)depotDao.getHibernateTemplate().getSessionFactory().getCurrentSession();
        LobHelper lh = se.getLobHelper();
        Blob blob = lh.createBlob(file.getBytes());

        Document newDocument = new Document();
        newDocument.setDescription(documentFormBean.getDescription());
        newDocument.setContentType(file.getContentType());
        newDocument.setFilename(file.getOriginalFilename());
        newDocument.setContent(blob);
        newDocument.setDepot(depotDao.find(Long.parseLong((String) request.getParameter("depot"))));
        documentDao.save(newDocument);
        map.put("documentList", documentDao.findAllForaDepot(Long.parseLong((String) request.getParameter("depot"))));
        } catch (IOException e) {
        e.printStackTrace();
    }

    return new ModelAndView("ajoutDocumentsRapport",map);
    }
}

Tomcat 6 AJP连接器连接器配置: (原始配置是:)

<Connector port="8009" protocol="AJP/1.3" redirectPort="8443"/>

(也试过这个:)

<Connector port="8009" protocol="AJP/1.3" redirectPort="8443"
             connectionTimeout="120000" maxThreads="1000"
            minSpareThreads="50" maxSpareThreads="100" enableLookups="false"
            acceptCount="150" address="127.0.0.1"
            useBodyEncodingForURI="true"
            compression="on"
            compressionMinSize="1024"
            compressableMimeType="text/html,text/xml"
            connectionUploadTimeout="3600000"
            disableUploadTimeout="true"
    />

Apache 2虚拟主机配置:

<VirtualHost *:80>
    ServerAdmin webmaster@localhost
    DocumentRoot /var/www
    Timeout 3600
    ProxyPass / ajp://localhost:8009/
    ProxyPassReverse / ajp://localhost:8009/
    ProxyTimeout 3600

    <Proxy *>
    Order deny,allow
    Allow from all
    </Proxy>

    <Directory /var/www/>
            Options -Indexes FollowSymLinks MultiViews
            AllowOverride None
            Order allow,deny
            allow from all
    </Directory>

     ScriptAlias /cgi-bin/ /usr/lib/cgi-bin/
     ErrorLog ${APACHE_LOG_DIR}/error.log
     LogLevel warn
    CustomLog ${APACHE_LOG_DIR}/access.log combined
</VirtualHost>

Html表格:

<%@ page language="java" contentType="text/html; charset=ISO-8859-1"
pageEncoding="ISO-8859-1"%>
<%@taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c"%>
<%@taglib uri="http://www.springframework.org/tags/form" prefix="form"%>
<%@taglib uri="http://www.springframework.org/tags" prefix="spring"%>
<%@ taglib uri="http://java.sun.com/jsp/jstl/functions" prefix="fn"%>
<%@ taglib uri="http://displaytag.sf.net" prefix="display"%>
<%@ taglib uri="http://java.sun.com/jsp/jstl/fmt" prefix="fmt"%>
<%@ page isELIgnored="false" %>

<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
<title>Insert title here</title>
<base
href="<%=request.getScheme() + "://" + request.getServerName()
                + ":" + request.getServerPort() + request.getContextPath()
                + "/"%>" />

<link href="css/style1.css" rel="stylesheet" type="text/css" />
<link href="css/style.css" rel="stylesheet" type="text/css" />
<link type="text/css" rel="stylesheet" href="css/solid.css" />
<link type="text/css" rel="stylesheet" href="css/errors.css" />
<script type="text/javascript" src="script/jquery-1.6.2.min.js"></script> 
<script type="text/javascript" src="script/jquery.validate.js"></script>

</head>
<body>  

<form:form id="myform" method="post" action="save.html" commandName="documentFormBean" enctype="multipart/form-data">

<c:set var="depot" value="${depot.id}" scope="session" />
<input type="hidden" name="depot" value="${depot.id}" /> 
<table id="gradient-style">
    <tr>
        <th colspan="8"><h3>Fichiers joints au rapport</h3>
        </th>
    </tr>

    <tr><td>->Ajouter un document</td>
        <td><form:textarea path="description" />
        <br/>
         <span style="color:red">*</span>description du fichier
        <form:errors path="description" cssClass="error" />
        </td>
        <td colspan="3">
        <input type="file" name="file" />
        <br/><span class="error" >${ErrorMessageFileEmpty}</span>
        <br/><span class="error" >${ErrorMessageFileTypeNotPDF}</span>
        <br/><span class="error" >${MaximumFileNumberReached}</span>
        </td>
        <td colspan="3"><input type="submit" id="upload" value="Ajouter le document" /></td>
    </tr>
    <tr > <td colspan="8"> <div style="color:red">Attention : le document doit comporter obligatoirement une description et un fichier PDF (taille maximum : 20Mo) </div></td></tr>
    <tr > <td colspan="8"> <div >Note : Si vous le déposant n'est pas autorisé à publier son rapport pour des raisons de confidentialité, déposer simplement la page de garde en pdf du rapport </div></td></tr>
</table>

<span class="error">${msg}</span>

    <c:if test="${!empty documentList}">    
    Liste des documents associés au rapport : 
    <table id="gradient-style">
    <tr>
        <th>Description</th>
        <th>Nom du fichier</th>
        <th>type de contenu</th>
        <th>T&eacute;l&eacute;charger</th>
        <th>Supprimer</th>
    </tr>


    <c:forEach items="${documentList}" var="document">
        <tr>

            <td width="250px">${document.description}</td>
            <td width="250px">${document.filename}</td>
            <td width="250px">${document.contentType}</td>
            <td width="20px"><a
                href="${pageContext.request.contextPath}/download/${document.id}.html"
                target="_blank"><img
                    src="${pageContext.request.contextPath}/images/save-icon.jpg"
                    width="20px" height="20px"
                    border="0" title="Download this document" />T&eacute;l&eacute;charger</a>
            </td>
            <td width="20px"><a
                href="${pageContext.request.contextPath}/remove/document/${document.id}/depot/${depot.id}.html"
                onclick="return confirm('Etes vous certain de vouloir supprimer ce fichier ?')"><img
                    width="20px" height="20px" src="${pageContext.request.contextPath}/images/delete-icon.jpg"
                    border="0" title="Delete this document" />Supprimer</a></td>
        </tr>
    </c:forEach>


    </table>
    </c:if>
    <script>
    function disp_warning()
    {
      alert("Vous devez ajouter au moins un document SVP !")
    }
    </script>
    <table id="gradient-style">
        <tr>
        <th colspan="6">
            <c:choose>
                 <c:when test="${fn:length(documentList) gt 0}">
                    <button type="button" onclick="location.href='endAdd.html'"><spring:message code="application.add.end.title"/>  </button>
                </c:when>
                <c:otherwise>
                    <button type="button" onclick="disp_warning()"><spring:message code="application.add.end.title"/></button>
                </c:otherwise>
            </c:choose>
        </th>
    </tr>

    </table>
</form:form>
</body>
</html>

这种例外的可能原因是什么?
文件上传时的连接重置通常意味着客户端中止发送...那么什么? 任何帮助将不胜感激。 Christophe D.

1 个答案:

答案 0 :(得分:2)

您是否可以在客户端和服务器之间捕获tcpdump,并查看谁正在重置连接。我们的应用程序中有一个类似的问题,它是一个防火墙,正在放弃连接。 apache [LimitRequestBody]中还有另一个设置,即在文件上传达到该限制后中止上传。在这两种情况下,来自apache和mod-jk的日志在这些情况下调试并不是很清楚。