Spring Boot打WAR包部署Tomcat后文件上传报错Required request part 'file'不存在
问题描述
最近两天在Stack Overflow查阅该问题的解决方案,尝试了所有相关问题的回答均未解决问题。该文件上传功能在Eclipse中以Spring Boot应用启动时运行正常,但将项目打成WAR包部署到外部Tomcat后就会抛出Required request part 'file' is not present错误。
报错信息
org.springframework.web.servlet.mvc.support.DefaultHandlerExceptionResolver:logException(207): Resolved [org.springframework.web.multipart.support.MissingServletRequestPartException: Required request part 'file' is not present]
已确认信息
通过Chrome浏览器网络面板查看提交的Form数据如下:
Content-Disposition: form-data; name="file"; filename="Flow_Results.xlsx"
Content-Type: application/vnd.openxmlformats-officedocument.spreadsheetml.sheet
可以确认文件确实存在于提交到服务端的表单中。
相关配置代码
1. Pom.xml依赖配置
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> <exclusions> <exclusion> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-logging</artifactId> </exclusion> </exclusions> </dependency> <!-- Tomcat --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-tomcat</artifactId> <scope>provided</scope> </dependency> <dependency> <groupId>commons-fileupload</groupId> <artifactId>commons-fileupload</artifactId> <version>1.4</version> </dependency>
2. Application.properties配置
spring.servlet.multipart.enabled=true spring.servlet.multipart.location=${java.io.tmpdir}
3. 前端Angular发起POST请求的代码
saveData(file: File, opertatorId: string): Observable<HttpEvent<{}>> { const formData: FormData = new FormData(); formData.append('file', file, file.name); const newRequest = new HttpRequest('POST', 'cliareport/savedatafile/' + opertatorId, formData, { reportProgress: true, responseType: 'text', }); return this.httpClient.request(newRequest); }
4. Spring Boot控制器及Multipart配置代码
@Bean public CommonsMultipartResolver multipartResolver() { CommonsMultipartResolver multipartResolver = new CommonsMultipartResolver(); multipartResolver.setMaxUploadSize(-1); return multipartResolver; } @PostMapping(path="/cliareport/savedatafile/{operatorid}", consumes = MediaType.MULTIPART_FORM_DATA_VALUE) public ResponseEntity<String> saveDataFile(@RequestParam("file") MultipartFile file, @PathVariable("operatorid") String operatorid) { }
问题原因
核心原因为Multipart解析器冲突:
- Spring Boot开启
spring.servlet.multipart.enabled=true后会默认加载StandardServletMultipartResolver处理文件上传请求 - 你又手动注册了
CommonsMultipartResolver,两个解析器同时存在时,部署到外部Tomcat会触发请求流重复读取的问题:第一次解析后请求流已经被消费,第二次解析时无法读取到file参数。内嵌Tomcat运行时因为类加载顺序差异未触发该问题,外部Tomcat的类加载逻辑和内嵌容器不同,因此暴露了冲突。
解决方案
以下两种方案二选一即可,推荐使用第一种方案:
方案一:移除CommonsMultipartResolver相关配置(推荐)
- 删除pom.xml中的
commons-fileupload依赖 - 删除手动定义的
multipartResolverBean代码 - 可根据业务需求在application.properties补充文件大小限制配置,示例如下:
spring.servlet.multipart.max-file-size=100MB spring.servlet.multipart.max-request-size=100MB
Spring Boot默认的StandardServletMultipartResolver完全可以满足常规文件上传需求,无需额外引入第三方依赖,也不需要手动配置解析器。
方案二:禁用Spring Boot默认Multipart自动配置
如果业务场景必须使用commons-fileupload,可按如下步骤修改:
- 将application.properties中的
spring.servlet.multipart.enabled改为false - 确保手动定义的
multartResolverBean名称为multipartResolver(当前配置的方法名已经匹配要求,无需额外修改)
额外排查点
如果修改配置后仍报错,可检查外部Tomcat的server.xml配置中Connector节点的maxPostSize参数,如果该值设置为0会限制POST请求大小,改为-1即可取消大小限制,或设置为符合业务需求的数值即可。
内容的提问来源于stack exchange,提问作者Craig Liston
相关产品推荐
相关产品推荐

