无法解析多部分servlet请求,嵌套异常为org.apache.commons.fileupload.FileUploadException


问题内容

通过使用CommonsMultipartResolver库在Spring中上传10 MB大小的csv文件时遇到错误。我已经在xml文件Xml File
Confi中进行了以下设置:

 <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)

问题答案:

正如 @ChristianMaioliM 在评论中所要求的那样,添加了有关以下内容的更多详细信息:代码中的问题是
BindingResult参数未遵循模型对象

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

参考docs
BindingResult和@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类中添加mulitpart / binding字段,例如:

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";
}