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处理大文件上传的两种方式:

  1. 一次性传输:适合中小文件,便于后续访问
  2. 流式API:大文件首选,内存效率更高

完整源码可在GitHub获取。


原始标题:Spring and Apache FileUpload