Spring Boot 3.2.2迁移后无法读取MultipartFile问题求助
问题描述
项目从Spring Boot 2迁移至Spring Boot 3.2.2后,文件上传功能失效。原基于javax servlet的commons-fileupload依赖,迁移到jakarta servlet后改用commons-fileupload2-jakarta仍未解决问题。无论通过表单提交还是Ajax结合FormData提交,均返回405错误,核心报错信息如下:
405 Servlet.service() for servlet [mvc-dispatcher] in context with path [/lmsadmin] threw exception [Request processing failed: org.springframework.web.multipart.MultipartException: Failed to parse multipart servlet request] with root cause java.lang.IllegalStateException: Unable to process parts as no multi-part configuration has been provided)
已尝试在@Controller上添加@MultipartConfig注解,并在application.properties中配置multipart相关参数,但问题依旧。
排查与解决方案
1. 移除@MultipartConfig注解
Spring Boot 3.x的spring-boot-starter-web已内置Jakarta Servlet的Multipart自动支持,手动添加@MultipartConfig(Servlet原生注解)会与Spring Boot的自动配置冲突,直接删除控制器上的该注解即可。
2. 清理application.properties冗余配置
Spring Boot 3.x仅使用spring.servlet.multipart前缀的配置,旧版spring.http.servlet.multipart配置已废弃,保留有效配置:
spring.servlet.multipart.max-file-size=10MB spring.servlet.multipart.max-request-size=10MB # 可选:自定义临时文件存储路径 # spring.servlet.multipart.location=/tmp
3. 删除commons-fileupload相关依赖
Spring Boot 3.x默认使用Servlet 6.0+原生Multipart处理机制,无需额外引入commons-fileupload或commons-fileupload2-jakarta依赖,直接移除这些依赖避免冲突。
4. 校验控制器映射路径
确认JSP表单的action="controller/upload"与控制器映射是否匹配:
- 若控制器类上有
@RequestMapping("/controller"),则映射正确; - 若无类级别
@RequestMapping,表单action需改为/upload(或结合项目上下文路径调整)。
5. 调整控制器参数注解(可选)
将@RequestPart替换为@RequestParam,部分场景下后者兼容性更好:
@PostMapping(value = "/upload", consumes = MediaType.MULTIPART_FORM_DATA_VALUE, produces = MediaType.APPLICATION_JSON_VALUE) public @ResponseBody String dopost(HttpSession session, @RequestParam(value = "file") MultipartFile file) throws IllegalStateException, IOException { // 业务逻辑处理 }
修正后核心代码示例
清理后的pom.xml关键依赖
<dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-tomcat</artifactId> <scope>provided</scope> </dependency> <!-- 保留其他业务依赖,移除commons-fileupload相关依赖 --> </dependencies>
修正后的控制器代码
@Controller @RequestMapping("/controller") // 对应表单action的controller前缀 public class UploadController { @PostMapping(value = "/upload", consumes = MediaType.MULTIPART_FORM_DATA_VALUE, produces = MediaType.APPLICATION_JSON_VALUE) public @ResponseBody String dopost(HttpSession session, @RequestParam(value = "file") MultipartFile file) throws IllegalStateException, IOException { // 文件上传逻辑 return "upload success"; } }
JSP代码保持不变
<form id="formInput" enctype="multipart/form-data" action="controller/upload" method="POST"> <input type="file" accept=".csv, application/vnd.openxmlformats-officedocument.spreadsheetml.sheet, application/vnd.ms-excel" id="files0" name="file" /> <button type="submit">上传</button> </form>
内容的提问来源于stack exchange,提问作者lauwis

