Spring Boot 3迁移:Commons FileUpload兼容问题及流式上传替代方案咨询
Spring Boot 3 流式大文件上传替代方案
一、Servlet API 原生流式支持
Servlet 6.x(Spring Boot 3 依赖的版本)本身就支持流式处理文件上传,无需第三方库:
- 通过
jakarta.servlet.http.Part接口,从HttpServletRequest.getParts()获取上传部件,直接调用part.getInputStream()拿到输入流,边读边写入远程文件共享,无需将整个文件加载到内存。 - 核心代码示例:
@PostMapping("/upload") public String handleUpload(HttpServletRequest request) throws IOException, ServletException { for (Part part : request.getParts()) { if (part.getContentType() != null) { try (InputStream inputStream = part.getInputStream(); OutputStream outputStream = new FileOutputStream("远程共享路径/" + part.getSubmittedFileName())) { byte[] buffer = new byte[8192]; int bytesRead; while ((bytesRead = inputStream.read(buffer)) != -1) { outputStream.write(buffer, 0, bytesRead); } } part.delete(); } } return "upload success"; }
- 需在控制器类上添加
@MultipartConfig注解,配置参数避免内存溢出:
@MultipartConfig( maxFileSize = 1024 * 1024 * 100, maxRequestSize = 1024 * 1024 * 500, fileSizeThreshold = 1024 * 1024 * 10, location = "/tmp" )
二、Spring Framework 封装的流式方案
Spring Boot 3 提供了更简洁的封装,同样支持流式处理:
1. MultipartFile 流式处理
MultipartFile可直接获取输入流,只要配置得当,超过阈值的文件会自动写入临时磁盘,不会占用过多内存:
@PostMapping("/spring-upload") public String springHandleUpload(@RequestParam("file") MultipartFile file) throws IOException { try (InputStream inputStream = file.getInputStream(); OutputStream outputStream = new FileOutputStream("远程共享路径/" + file.getOriginalFilename())) { byte[] buffer = new byte[8192]; int bytesRead; while ((bytesRead = inputStream.read(buffer)) != -1) { outputStream.write(buffer, 0, bytesRead); } } return "upload success"; }
- 在
application.properties中配置上传参数:
spring.servlet.multipart.max-file-size=100MB spring.servlet.multipart.max-request-size=500MB spring.servlet.multipart.file-size-threshold=10MB spring.servlet.multipart.location=/tmp
2. StreamingMultipartParser 全流式解析
Spring MVC 6.x 提供的StreamingMultipartParser可直接解析请求流,全程流式处理,几乎不占用内存:
@PostMapping(value = "/streaming-upload", consumes = MediaType.MULTIPART_FORM_DATA_VALUE) public String streamingUpload(HttpServletRequest request) throws IOException { StreamingMultipartParser parser = new StreamingMultipartParser(request) .setCharset(StandardCharsets.UTF_8); while (parser.hasNext()) { PartEvent event = parser.next(); if (event instanceof FilePartEvent filePartEvent) { try (InputStream inputStream = filePartEvent.content(); OutputStream outputStream = new FileOutputStream("远程共享路径/" + filePartEvent.filename())) { inputStream.transferTo(outputStream); } event.close(); } } return "upload success"; }
三、关键注意事项
- 优先使用NIO类库或专门的文件共享客户端(如SMB客户端)处理远程写入,提升传输效率。
- 严格配置文件大小阈值,确保大文件自动写入临时磁盘,避免内存溢出。
- 超大型文件可结合分片上传逻辑,进一步降低单请求的内存压力。
内容的提问来源于stack exchange,提问作者dOcean
相关产品推荐
相关产品推荐

