Spring Boot实现超2GB大文件直接上传至服务器文件夹(跳过临时文件)
问题描述
在Spring Boot中上传超过2GB的大文件到指定文件夹时,发现请求需要50多秒才到达控制器。调试后得知,使用MultipartFile时文件会先完整上传到临时文件夹,再复制到目标文件夹,最后删除临时文件,这大幅增加了执行时间。希望实现直接将文件上传至目标文件夹,跳过临时文件流程。
当前代码
Controller
@RestController public class UploadData{ @Autowired private UploadService uploadService; @PostMapping("/upload_file") protected UploadResponse uploadFile(@ModelAttribute UserUpload user, @RequestParam MultipartFile file) throws IOException,SQLException { return uploadService.uploadFile(user, file); } }
Service
@Service public class UploadService { @Value(value = "${file.upload.dir}") String fileUploadDir; public UploadResponse uploadFile(UserUpload user, MultipartFile file) throws IOException, SQLException { Path uploadFolder = Paths.get(fileUploadDir); Path fileUploadPath = uploadFolder.resolve(file.getOriginalFilename()); Files.copy(file.getInputStream(), fileUploadPath, StandardCopyOption.REPLACE_EXISTING); String basename = FilenameUtils.getBaseName(file.getOriginalFilename()); return new UploadResponse(basename + "Uploaded Successfully"); } else { return new UploadResponse("Failed To Upload Data Set"); } }
解决方案
1. 使用Part替代MultipartFile,直接流式写入目标文件
Spring Boot底层基于Servlet,Part可以直接获取文件输入流,无需经过临时文件存储。修改Controller和Service:
修改后的Controller
@RestController public class UploadData{ @Autowired private UploadService uploadService; @PostMapping("/upload_file") protected UploadResponse uploadFile(@ModelAttribute UserUpload user, @RequestParam("file") Part file) throws IOException,SQLException { return uploadService.uploadFile(user, file); } }
修改后的Service
@Service public class UploadService { @Value(value = "${file.upload.dir}") String fileUploadDir; public UploadResponse uploadFile(UserUpload user, Part file) throws IOException, SQLException { Path uploadFolder = Paths.get(fileUploadDir); // 确保目标文件夹存在 if (!Files.exists(uploadFolder)) { Files.createDirectories(uploadFolder); } String fileName = file.getSubmittedFileName(); Path fileUploadPath = uploadFolder.resolve(fileName); // 直接将Part的输入流写入目标文件 try (InputStream inputStream = file.getInputStream(); OutputStream outputStream = Files.newOutputStream(fileUploadPath, StandardOpenOption.CREATE, StandardOpenOption.TRUNCATE_EXISTING)) { byte[] buffer = new byte[8192]; int bytesRead; while ((bytesRead = inputStream.read(buffer)) != -1) { outputStream.write(buffer, 0, bytesRead); } } String basename = FilenameUtils.getBaseName(fileName); return new UploadResponse(basename + "Uploaded Successfully"); } catch (Exception e) { e.printStackTrace(); return new UploadResponse("Failed To Upload Data Set"); } }
2. 配置Spring Boot跳过Multipart临时存储
在配置文件中添加以下设置,禁用Multipart的临时文件存储,强制流式处理:
application.properties
# 禁用Multipart临时文件存储 spring.servlet.multipart.enabled=true spring.servlet.multipart.file-size-threshold=0 spring.servlet.multipart.location= # 留空表示不使用临时目录 # 设置最大文件大小和请求大小 spring.servlet.multipart.max-file-size=5GB spring.servlet.multipart.max-request-size=5GB # Tomcat配置,防止大文件上传被截断 server.tomcat.max-swallow-size=-1
application.yml
spring: servlet: multipart: enabled: true file-size-threshold: 0 location: "" # 不指定临时目录 max-file-size: 5GB max-request-size: 5GB server: tomcat: max-swallow-size: -1 # 允许无限大小的请求体
3. 注意事项
- 确保目标文件夹具备足够的读写权限,避免IO异常。
- 大文件上传建议搭配客户端分块上传逻辑,避免单次请求超时,提升容错性。
- 生产环境需添加文件重名处理逻辑,防止覆盖已有文件。
内容的提问来源于stack exchange,提问作者Janeth Jackson
相关产品推荐
相关产品推荐

