1. 概述
Apache Commons FileUpload库帮助我们通过HTTP协议使用multipart/form-data
内容类型上传大文件。这篇指南将展示如何将其与Spring框架集成。
2. Maven依赖
使用该库需要添加commons-fileupload2-jakarta
依赖:
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-fileupload2-jakarta</artifactId>
<version>2.0.0-M1</version>
</dependency>
最新版本可在Maven Central获取。
3. 一次性传输方式
创建Controller处理文件上传请求:
@PostMapping("/upload")
public String handleUpload(HttpServletRequest request) throws Exception {
boolean isMultipart = JakartaServletFileUpload.isMultipartContent(request);
DiskFileItemFactory factory = DiskFileItemFactory.builder().get();
JakartaServletFileUpload upload = new JakartaServletFileUpload(factory);
List items = upload.parseRequest(request);
Iterator iter = items.iterator();
while (iter.hasNext()) {
FileItem item = iter.next();
if (!item.isFormField()) {
try (
InputStream uploadedStream = item.getInputStream();
OutputStream out = new FileOutputStream("file.mov");) {
IOUtils.copy(uploadedStream, out);
}
}
}
return "success!";
}
关键点说明:
- ✅ 使用
isMultipartContent
检查请求是否包含多部分内容 - ⚠️ 必须禁用Spring的MultipartResolver,否则会提前读取请求内容:
spring.http.multipart.enabled=false
DiskFileItemFactory
负责文件保存和清理的配置- 通过
FileItem
抽象处理表单字段 - 使用
IOUtils.copy
简化流复制操作
这种方式便于文件访问,但内存和时间效率不是最优解
4. 流式API
流式API无需临时文件,适合处理大文件:
JakartaServletFileUpload upload = new JakartaServletFileUpload();
FileItemInputIterator iterStream = upload.getItemIterator(request);
while (iterStream.hasNext()) {
FileItemInput item = iterStream.next();
String name = item.getFieldName();
InputStream stream = item.getInputStream();
if (!item.isFormField()) {
// 处理文件流
} else {
String formFieldValue = IOUtils.toString(stream, StandardCharsets.UTF_8);
}
}
核心优势:
- ❌ 不需要
DiskFileItemFactory
- ✅ 使用
FileItemInputIterator
延迟读取请求内容 - ✅ 直接处理输入流,避免中间文件
- ✅ 同时支持普通表单字段获取
5. 总结
本文展示了在Spring中使用Apache Commons FileUpload处理大文件上传的两种方式:
- 一次性传输:适合中小文件,便于后续访问
- 流式API:大文件首选,内存效率更高
完整源码可在GitHub获取。