【问题标题】:Could not parse multipart servlet request, nested exception is org.apache.commons.fileupload.FileUploadException无法解析多部分 servlet 请求,嵌套异常是 org.apache.commons.fileupload.FileUploadException
【发布时间】:2022-01-13 13:16:03
【问题描述】:

当我使用 CommonsMultipartResolver 库在 Spring 中上传 10 MB 大小的 csv 文件时出现错误。我已经在 xml 文件中完成了以下设置 Xml 文件配置:

 <beans:bean id="multipartResolver"
class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
<!-- max upload size in bytes -->
<beans:property name="maxUploadSize" value="99971520" /> <!-- 99MB -->

<!-- max size of file in memory (in bytes) -->
<beans:property name="maxInMemorySize" value="1048576" /> <!-- 1MB -->

控制器代码:

 @RequestMapping(value="/uploadForm",method = RequestMethod.POST)
public @ResponseBody  String  uploadForm1(@ModelAttribute("admin") BillingAndRecon  billingandrecon,@RequestParam String id,BindingResult result,Principal principal,@RequestParam MultipartFile file,HttpSession session) throws ServiceException, DaoException, IllegalStateException, IOException {


    File uploadFile = null;
    String msg = "";

    if (!file.getOriginalFilename().equals("")) {

        logger.info("Before  Multipart file get path >> ");
        BillingAndReconServiceImpl asi = (BillingAndReconServiceImpl) this.billingAndReconService;// not correct!!
        String uploadDirectoryPath = asi.getUploadDirectoryPath(); // not correct!!

        uploadFile = new File( uploadDirectoryPath + file.getOriginalFilename());
        logger.info("Before  Multipart file get path uploadDirectoryPath >> "+uploadDirectoryPath);
        file.transferTo(uploadFile);
    }
}

表单页面:

<form:form action="./uploadForm" method="post" enctype="multipart/form-data" ModelAttribute=="admin">
          <input type="file" name="file" />
          <input type="text" name="id" />
           </form:form>

但我不明白什么是问题。我尝试设置大小和设置标题也enctype="multipart/form-data",但尚未解决。

以下是错误:

org.springframework.web.multipart.MultipartException: Could not parse multipart servlet request; nested exception is org.apache.commons.fileupload.FileUploadException: the request was rejected because no multipart boundary was found] with root cause org.apache.commons.fileupload.FileUploadException: the request was rejected because no multipart boundary was found
at org.apache.commons.fileupload.FileUploadBase$FileItemIteratorImpl.<init>(FileUploadBase.java:954)
at org.apache.commons.fileupload.FileUploadBase.getItemIterator(FileUploadBase.java:331)
at org.apache.commons.fileupload.FileUploadBase.parseRequest(FileUploadBase.java:351)
at org.apache.commons.fileupload.servlet.ServletFileUpload.parseRequest(ServletFileUpload.java:126)
at org.springframework.web.multipart.commons.CommonsMultipartResolver.parseRequest(CommonsMultipartResolver.java:156)
at org.springframework.web.multipart.commons.CommonsMultipartResolver.resolveMultipart(CommonsMultipartResolver.java:139)
at org.springframework.web.servlet.DispatcherServlet.checkMultipart(DispatcherServlet.java:1047)
at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:892)
at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:856)
at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:920)
at org.springframework.web.servlet.FrameworkServlet.doPost(FrameworkServlet.java:827)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:647)
at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:801)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:728)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:305)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:210)
at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:222)
at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:123)
at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:502)
at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:171)
at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:99)
at org.apache.catalina.valves.AccessLogValve.invoke(AccessLogValve.java:953)
at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:118)
at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:408)
at org.apache.coyote.http11.AbstractHttp11Processor.process(AbstractHttp11Processor.java:1023)
at org.apache.coyote.AbstractProtocol$AbstractConnectionHandler.process(AbstractProtocol.java:589)
at org.apache.tomcat.util.net.JIoEndpoint$SocketProcessor.run(JIoEndpoint.java:310)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1145)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:615)
at java.lang.Thread.run(Thread.java:744)

【问题讨论】:

    标签: spring-mvc


    【解决方案1】:

    正如 @ChristianMaioliM 在评论中要求的那样,添加了更多关于 您的代码中的问题是BindingResult 参数未遵循模型对象

    Errors 或 BindingResult 参数必须跟在被立即绑定的模型对象之后,因为方法签名可能有多个模型对象,并且 Spring 将为它们中的每一个创建一个单独的 BindingResult 实例,因此以下示例将不起作用

    参考文档Invalid ordering of BindingResult and @ModelAttribute

    要解决此问题,请更改控制器方法处理程序签名以遵循 BindingResult 和模型对象之间的参数顺序,例如:

    发件人:

    @RequestMapping(value="/uploadForm",method = RequestMethod.POST)
    public @ResponseBody  String  uploadForm1(@ModelAttribute("admin") BillingAndRecon  billingandrecon,@RequestParam String id,BindingResult result,Principal principal,@RequestParam MultipartFile file,HttpSession session) throws ServiceException, DaoException, IllegalStateException, IOException {
    

    收件人:

    @RequestMapping(value="/uploadForm",method = RequestMethod.POST)
    public String  uploadForm1(
                @ModelAttribute("admin") BillingAndRecon billingandrecon, 
                BindingResult result,
                Principal principal,
                HttpSession session) throws ServiceException, DaoException, IllegalStateException, IOException {
      //do file save here
      return "some-view-name";
    }
    

    并在 BillingAndRecon 类中添加多部分/绑定字段,例如:

    public class BillingAndRecon {
      private MultipartFile file;
      private String id;
    
      no-arg constructor;
      getters;
      setters;
    }
    

    注意: BindingResult 参数应该在@ModelAttrubiute/@RequestBody 的立即数之后

    和jsp形式:

    <form:form action="${pageContext.request.contextPath}/uploadForm"  
       method="post" 
       enctype="multipart/form-data" 
       modelAttribute="admin">
          <input type="file" name="file" />
          <form:input path="id" />
    </form:form>
    

    并且不要忘记在 GET 处理程序中添加绑定实例,例如:

    @RequestMapping(value="/uploadForm",method = RequestMethod.GET)
    public String uploadFormView(Model model){
      model.addAttribute("admin", new BillingAndRecon());
      return "your-upload-view-name";
    }
    

    【讨论】:

    • 尚未解决问题。今天我仍然面临问题。您能否提供任何其他解决方案。我跟踪我的 contentType 我在我的 servlet 过滤所有 IE broser 中得到 null 为什么?
    • 请解释你的答案,不要只发布“这样做”,否则其他有类似问题的人不会明白你的实施背后的想法。
    • @ChristianMaioliM。答案已编辑以添加详细说明。
    【解决方案2】:

    有时,如果过滤器链中有任何特定于应用程序的过滤器,并且如果它们正在关闭流,则您会收到此异常。 从异常堆栈跟踪中,查找是否存在任何特定于应用程序的过滤器并禁用它们并检查

    【讨论】:

      【解决方案3】:

      org.springframework.web.multipart.MultipartException:解析多部分servlet请求失败;嵌套异常是 java.io.IOException: org.apache.tomcat.util.http.fileupload.FileUploadException: Stream closed

      在 Spring Boot 2.1.12 上运行良好,升级到 2.2.4 后失败(两个版本运行相同的嵌入式 Tomcat 9.0.30)。

      根本原因是我们使用了 logback-access 过滤器来记录请求和响应。过滤器使用缓存包装器包装 HttpServletRequest 并在沿过滤器链传递请求之前关闭输入流。这在调用 javax.servlet.http.HttpServletRequest#getParts 时导致了一个问题,因为该调用被委托给原始 Tomcat 的请求(具有现在关闭的输入流),然后导致“流关闭”异常。

      触发此问题的 Spring 更改是 hiddenHttpMethodFilter 不再存在于过滤器链中。以前这个过滤器是第一个被调用的过滤器,它会调用 HttpServletRequest#getParameter,这反过来会使 Tomcat 的请求实现解析多部分内容并将这些部分存储在对象中(以便以后调用#getParts 将使用并且不再尝试解析它们)。

      我将此报告给 Logback:https://jira.qos.ch/browse/LOGBACK-1503

      解决方法 - 在将请求传递给 logback 的过滤器之前调用 HttpServletRequest#getParameter(有关代码,请参阅 LOGBACK-1503),以强制 Tomcat 在输入流仍处于打开状态时解析和存储请求部分。

      【讨论】:

        猜你喜欢
        • 2020-03-14
        • 2015-12-17
        • 2014-09-21
        • 1970-01-01
        • 2014-10-10
        • 2016-08-16
        • 2015-09-24
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多