You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.24 13:20:40