2012-10-24 50 views
5

我得到了一個表單,屬於一個web應用程序,其中包含一個用於上傳pdf文件的「文件」字段(彈簧3環境,多部分文件上傳) 上傳文件正常工作在測試環境(所有瀏覽器)中,並且只能在生產環境中使用Firefox(文件上傳導致連接重置異常,尤其是低互聯網連接客戶端瀏覽器)上傳文件問題彈簧3 - MultipartException,連接重置

提交按鈕被按下後幾秒鐘會拋出以下異常:瀏覽器是在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 

這裏是網絡應用程序代碼和配置:

彈簧multipart解析器配置:

控制器:

/**  
* this controller handles file upload and save files to dao. 
    * @author [email protected] 
    * @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 [email protected] 
    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.

+0

你可以發佈你的HTML表單,看起來像表單編碼的問題。 –

+0

hi Jigar,剛剛編輯了這個線程,你現在可以看到html表單。謝謝。 –

+1

我很確定你的生產服務器前面有一個防火牆/負載平衡器,即使你的應用服務器允許一個很大的上傳超時,它也會在一定的超時後終止連接。我會做的是在開發工具打開的情況下在生產環境中嘗試此操作,以查看上傳失敗後的時間。如果您注意到在每個瞬間失敗發生在x秒後,您知道您的基礎設施正在關閉連接。 – Akshay

回答

2

您能捕獲客戶端和服務器之間的tcpdump並查看誰重置連接。我們在應用程序中遇到了類似的問題,它是一個防火牆,它正在斷開連接。在apache [LimitRequestBody]中有另一個設置,在文件上傳達到該限制之後放棄上載。在這兩種情況下,來自apache和mod-jk的日誌在這些情況下調試並不明顯。