【问题标题】:Spring REST API with Multipart File Upload not working for optional parameter带有多部分文件上传的 Spring REST API 不适用于可选参数
【发布时间】:2015-04-10 01:01:51
【问题描述】:

我正在使用 Spring 框架,但对它不太熟悉。我正在编写一个 REST API,特别是一个处理文件上传的 POST 方法,其中文件是可选的。

我已尝试简化方法,但仍有问题。这是我所拥有的

@RequestMapping(method = RequestMethod.POST, value="/items")
public String create(@RequestParam(value="file", required=false) MultipartFile file) {
    return "Create";
}

当我在表单请求中包含文件时,该方法可以正常工作,但是当我没有文件时(因为我希望它是可选的)。我尝试用HttpServletRequest 参数替换@RequestParam,得到相同的结果。

我收到以下堆栈跟踪的 500 错误:

java.io.IOException: org.apache.tomcat.util.http.fileupload.FileUploadException: Stream ended unexpectedly
    org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:973)
    org.springframework.web.servlet.FrameworkServlet.doPost(FrameworkServlet.java:863)
    javax.servlet.http.HttpServlet.service(HttpServlet.java:646)
    org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:837)
    javax.servlet.http.HttpServlet.service(HttpServlet.java:727)
    org.springframework.web.filter.HiddenHttpMethodFilter.doFilterInternal(HiddenHttpMethodFilter.java:77)
    org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
</pre></p><p><b>root cause</b> <pre>org.springframework.web.multipart.MultipartException: Could not parse multipart servlet request; nested exception is java.io.IOException: org.apache.tomcat.util.http.fileupload.FileUploadException: Stream ended unexpectedly
    org.springframework.web.multipart.support.StandardMultipartHttpServletRequest.parseRequest(StandardMultipartHttpServletRequest.java:99)
    org.springframework.web.multipart.support.StandardMultipartHttpServletRequest.&lt;init&gt;(StandardMultipartHttpServletRequest.java:77)
    org.springframework.web.multipart.support.StandardServletMultipartResolver.resolveMultipart(StandardServletMultipartResolver.java:76)
    org.springframework.web.servlet.DispatcherServlet.checkMultipart(DispatcherServlet.java:1067)
    org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:906)
    org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:870)
    org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:961)
    org.springframework.web.servlet.FrameworkServlet.doPost(FrameworkServlet.java:863)
    javax.servlet.http.HttpServlet.service(HttpServlet.java:646)
    org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:837)
    javax.servlet.http.HttpServlet.service(HttpServlet.java:727)
    org.springframework.web.filter.HiddenHttpMethodFilter.doFilterInternal(HiddenHttpMethodFilter.java:77)
    org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
</pre></p><p><b>root cause</b> <pre>java.io.IOException: org.apache.tomcat.util.http.fileupload.FileUploadException: Stream ended unexpectedly
    org.apache.catalina.connector.Request.parseParts(Request.java:2806)
    org.apache.catalina.connector.Request.parseParameters(Request.java:3096)
    org.apache.catalina.connector.Request.getParameter(Request.java:1145)
    org.apache.catalina.connector.RequestFacade.getParameter(RequestFacade.java:382)
    org.springframework.web.filter.HiddenHttpMethodFilter.doFilterInternal(HiddenHttpMethodFilter.java:70)
    org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
</pre></p><p><b>root cause</b> <pre>org.apache.tomcat.util.http.fileupload.FileUploadException: Stream ended unexpectedly
    org.apache.tomcat.util.http.fileupload.FileUploadBase.parseRequest(FileUploadBase.java:311)
    org.apache.catalina.connector.Request.parseParts(Request.java:2737)
    org.apache.catalina.connector.Request.parseParameters(Request.java:3096)
    org.apache.catalina.connector.Request.getParameter(Request.java:1145)
    org.apache.catalina.connector.RequestFacade.getParameter(RequestFacade.java:382)
    org.springframework.web.filter.HiddenHttpMethodFilter.doFilterInternal(HiddenHttpMethodFilter.java:70)
    org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
</pre></p><p><b>root cause</b> <pre>org.apache.tomcat.util.http.fileupload.MultipartStream$MalformedStreamException: Stream ended unexpectedly
    org.apache.tomcat.util.http.fileupload.MultipartStream.readHeaders(MultipartStream.java:480)
    org.apache.tomcat.util.http.fileupload.FileUploadBase$FileItemIteratorImpl.findNextItem(FileUploadBase.java:889)
    org.apache.tomcat.util.http.fileupload.FileUploadBase$FileItemIteratorImpl.&lt;init&gt;(FileUploadBase.java:854)
    org.apache.tomcat.util.http.fileupload.FileUploadBase.getItemIterator(FileUploadBase.java:259)
    org.apache.tomcat.util.http.fileupload.FileUploadBase.parseRequest(FileUploadBase.java:283)
    org.apache.catalina.connector.Request.parseParts(Request.java:2737)
    org.apache.catalina.connector.Request.parseParameters(Request.java:3096)
    org.apache.catalina.connector.Request.getParameter(Request.java:1145)
    org.apache.catalina.connector.RequestFacade.getParameter(RequestFacade.java:382)
    org.springframework.web.filter.HiddenHttpMethodFilter.doFilterInternal(HiddenHttpMethodFilter.java:70)
    org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)

我在网络上的搜索中只找到了一篇文章,它谈到这可能是 Spring 中的一个错误。我已经被这个问题困扰了一段时间,非常感谢一些帮助。

谢谢

【问题讨论】:

  • 这个错误是只出现在 Internet Explorer 还是所有浏览器中?尝试在表单中添加隐藏的输入字段。确保这个隐藏的表单域有一个虚拟值并且位于表单的末尾。
  • 您的表单帖子中有 enctype 属性吗?它的价值是什么?
  • 我正在使用 Chrome 应用程序来测试通话。我尝试包含不同的 enctype 属性,但没有成功。我实际上想出了如何做到这一点。我不知道它是否是最佳的。我所做的是,我对方法进行了签名,不包含任何使用 Multipart 的内容,而是包含 HttpServletRequest 的参数,然后在主体中我将对象转换为 MultipartHttpServletRequest 类型。我现在能够处理这两种类型。感谢您的 cmets
  • @GeekyDevs 你能在答案部分提供你的解决方案吗?

标签: java spring rest file-upload multipart


【解决方案1】:

这是我最终得到的解决方案。

@RequestMapping(method = RequestMethod.POST, value = "/object")
ResponseEntity<Object> create(@RequestParam("is_file") boolean isFile, HttpServletRequest request) {
    if(isFile) {
      MultipartHttpServletRequest multipartRequest = (MultipartHttpServletRequest) request;
      MultipartFile file = multipartRequest.getFile("file");
    } else{
      // You can add other parameters (as long as it isn't a multipart parameter) and do other stuff here
    }

}

【讨论】:

    【解决方案2】:

    我可以看到问题有点老了,但我把我的答案放在这里,因为上传文件主题总是存在的。 我在这个问题的上下文中测试了 Spring Boot 1.3.5.RELEASE。 我如下定义了休息服务,当文件未附加到多部分/表单数据时它可以工作。 我用 RestTemplate 客户端测试了服务。

    @RequestMapping(method = RequestMethod.POST)
    public ResponseEntity<String> upload(@RequestPart(value = "name", required = false) String name,
                                         @RequestPart(value = "file", required = false) MultipartFile file) 
    

    【讨论】:

      【解决方案3】:

      我遇到了同样的问题,只是添加 required=false 对我有用。请在下面找到示例代码,

      @RequestMapping(method = RequestMethod.POST, value="/items")
      public String create(@RequestParam(value ="file", required=false) MultipartFile file) {
          return "Create";
      }
      

      【讨论】:

        猜你喜欢
        • 2016-04-23
        • 2018-01-30
        • 2018-08-06
        • 2018-10-10
        • 2021-02-04
        • 1970-01-01
        • 2017-04-25
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多