文件上传报org.apache.tomcat.util.http.fileupload.FileUploadException: Stream closed
先上解决方式:
在yml或者其他配置文件中添加如下配置即可
Spring:
mvc:
hiddenmethod:
filter:
enabled: true
问题解决完毕、梳理下问题点【可忽略如下内容】
最近突然发现项目的上传功能失效了,一顿操作发现错误是:
org.apache.tomcat.util.http.fileupload.FileUploadException: Stream closed
尝试着各种解决未果,百度又是各种牛头不对马嘴。折腾了几个小时,皇天不负有心人。终于找到了一位老哥在gitmemory上提交的问题
url
:https://www.gitmemory.com/issue/spring-projects/spring-boot/18644/583836701
问题:
Upload file org.springframework.web.multipart.MultipartException
When updating Spring Boot to version 2.2.0 I get an error when trying to upload a file.
org.springframework.web.multipart.MultipartException: Failed to parse multipart servlet request; nested exception is java.io.IOException: org.apache.tomcat.util.http.fileupload.FileUploadException: Stream closed
Error code
@RestController
public class FileController {
@PostMapping("/api/file")
public ResponseEntity<String> upload(@RequestParam("file") MultipartFile multipartFile) {
//...
}
}
This code worked for me on versions less than 2.2.0
思路:
I ran into the same issue.
org.springframework.web.multipart.MultipartException: Failed to parse multipart servlet request; nested exception is java.io.IOException: org.apache.tomcat.util.http.fileupload.FileUploadException: Stream closed
Worked fine on Spring Boot 2.1.12, failed after upgrade to 2.2.4 (both versions run the same embedded Tomcat 9.0.30).
The root cause was that we were using logback-access filter that logs requests and responses. The filter wrapped HttpServletRequest with a caching wrapper and closed the input stream before passing the request along the filter chain. This caused an issue when javax.servlet.http.HttpServletRequest#getParts was called, as that call is delegated to the original Tomcat's request (with a now-closed input stream), which then results in the "stream closed" exception.
The Spring change that triggered this issue is hiddenHttpMethodFilter no longer being present in the filter chain. Previously this filter would be one of the first filters to be called, and it would call HttpServletRequest#getParameter, which in turn would make Tomcat's request implementation parse multipart content and store the parts in the object (so that later calls to #getParts would use that and not try to parse them again).
I reported this to Logback: https://jira.qos.ch/browse/LOGBACK-1503
Workaround - call HttpServletRequest#getParameter before passing the request to logback's filter (see LOGBACK-1503 for code), to force Tomcat to parse and store request parts while input stream is still open.
logback链接:
https://jira.qos.ch/browse/LOGBACK-1503
解析:
上面的老哥分析我看的也是一致半解
他是项目在升级到springboot2.2+时候出现的问题与我的问题一致
,简单的查看可知在springboot2.2+中把 META-INF/spring-configuration-metadata.json 配置文件中把spring.mvc.hiddenmethod.filter.enabled设置为了false
{
"name": "spring.mvc.hiddenmethod.filter.enabled",
"type": "java.lang.Boolean",
"description": "Whether to enable Spring's HiddenHttpMethodFilter.",
"defaultValue": false
}
至于为什么会出现这个问题,emmm我还得梳理下源码【待补充】