✅ Spring Boot 中文件上传的两种解析器比较
项目 |
CommonsMultipartResolver |
StandardServletMultipartResolver (Spring Boot 默认) |
依赖库 |
Apache Commons FileUpload(外部依赖) |
Servlet 3.0+(Java 原生) |
是否默认启用 |
❌ 否(需手动配置 Bean) |
✅ 是(Spring Boot 自动配置) |
是否懒加载 |
❌ 否(调用 resolveMultipart() 时立即解析) |
✅ 是(延迟到调用 getParts() 时解析) |
是否自动封装为 MultipartHttpServletRequest |
❌ 否(你需要手动传给下游) |
✅ 是(Spring 自动封装并传递) |
是否会提前消费请求流 |
✅ 是(流会被读取) |
❌ 否(不消费流,基于 Servlet 3 API) |
是否调用 setMultipartFiles() (注册上传文件) |
✅ 是(在 resolveMultipart() 中) |
✅ 是(内部自动处理) |
✅ 常见错误使用示例(你的情况)
1 2 3 4 5 6
| CommonsMultipartResolver resolver = new CommonsMultipartResolver(); if (resolver.isMultipart(request)) { MultipartHttpServletRequest multipartRequest = resolver.resolveMultipart(request); filterChain.doFilter(request, response); }
|
✅ 正确使用 CommonsMultipartResolver 的方式:
1 2 3 4 5 6 7 8
| CommonsMultipartResolver resolver = new CommonsMultipartResolver(); if (resolver.isMultipart(request)) { MultipartHttpServletRequest multipartRequest = resolver.resolveMultipart(request); filterChain.doFilter(multipartRequest, response); } else { filterChain.doFilter(request, response); }
|
✅ 如果你使用的是 StandardServletMultipartResolver:
1 2 3 4 5 6
| StandardServletMultipartResolver resolver = new StandardServletMultipartResolver(); if (resolver.isMultipart(request)) { } filterChain.doFilter(request, response);
|
为什么StandardServletMultipartResolver不会影响后面的处理呢?
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26
| private void parseRequest(HttpServletRequest request) { try { Collection<Part> parts = request.getParts(); this.multipartParameterNames = new LinkedHashSet<>(parts.size()); MultiValueMap<String, MultipartFile> files = new LinkedMultiValueMap<>(parts.size()); for (Part part : parts) { String headerValue = part.getHeader(HttpHeaders.CONTENT_DISPOSITION); ContentDisposition disposition = ContentDisposition.parse(headerValue); String filename = disposition.getFilename(); if (filename != null) { if (filename.startsWith("=?") && filename.endsWith("?=")) { filename = MimeDelegate.decode(filename); } files.add(part.getName(), new StandardMultipartFile(part, filename)); } else { this.multipartParameterNames.add(part.getName()); } } setMultipartFiles(files); } catch (Throwable ex) { handleParseFailure(ex); } }
|
- setMultipartFiles(files),在 Spring 的 MultipartHttpServletRequest 对象中注册上传的文件信息,以供后续使用(如 Controller 中的 @RequestParam MultipartFile file 获取文件)。
🧠 重点记忆:
- ✅ StandardServletMultipartResolver 更推荐,Spring Boot 默认支持,懒加载不消费流。
- ❌ CommonsMultipartResolver 不推荐使用于 Spring Boot,若使用必须手动传递解析后的 MultipartRequest,否则上传失败。
- ⚠️ 一旦提前用
.getInputStream()
或 .getBytes()
消费流,Controller 中将无法再获取文件。