全部学科
Python全栈
python
NodeJS全栈
nodejs
小程序首页
📅 2026-05-18 6 分钟 ✍️ juanwangdev

Spring MVC 文件上传原理与配置

理解文件上传原理有助于正确配置和处理文件上传请求。

multipart请求原理

HTTP multipart请求格式

Java
POST /upload HTTP/1.1
Content-Type: multipart/form-data; boundary=----WebKitFormBoundary

------WebKitFormBoundary
Content-Disposition: form-data; name="file"; filename="test.jpg"
Content-Type: image/jpeg

[文件二进制数据]
------WebKitFormBoundary
Content-Disposition: form-data; name="description"

文件描述文本
------WebKitFormBoundary--

multipart请求特点

  • Content-Type为multipart/form-data
  • boundary分隔符分割各部分数据
  • 每部分包含Content-Disposition和Content-Type头
  • 文件部分包含filename属性和二进制数据

StandardServletMultipartResolver

Spring MVC默认使用Servlet 3.0+的multipart支持:

YAML
@Configuration
public class MultipartConfig {

    @Bean
    public MultipartResolver multipartResolver() {
        return new StandardServletMultipartResolver();
    }
}

配置项详解

application.yml配置

Java
spring:
  servlet:
    multipart:
      enabled: true                    # 启用multipart支持
      max-file-size: 10MB              # 单文件最大大小
      max-request-size: 100MB          # 总请求最大大小
      file-size-threshold: 2KB         # 内存阈值
      location: /tmp/upload            # 临时文件目录
      resolve-lazily: false            # 延迟解析

配置项说明

配置项说明默认值
enabled是否启用multiparttrue
max-file-size单文件最大大小1MB
max-request-size请求总大小10MB
file-size-threshold内存阈值,超过写入临时文件0
location临时文件存储位置系统临时目录
resolve-lazily是否延迟解析multipartfalse

MultipartFile接口

Java
public interface MultipartFile extends InputStreamSource {

    String getName();              // 表单参数名
    String getOriginalFilename();  // 原始文件名
    String getContentType();       // 文件ContentType
    boolean isEmpty();             // 是否为空
    long getSize();                // 文件大小
    byte[] getBytes();             // 获取文件字节
    InputStream getInputStream();  // 获取输入流
    void transferTo(File dest);    // 保存到目标文件
}

文件上传处理流程

Java
HTTP multipart请求
    ↓
StandardServletMultipartResolver解析
    ↓
请求包装为StandardMultipartHttpServletRequest
    ↓
提取各部分数据封装为MultipartFile
    ↓
Controller通过@RequestParam接收MultipartFile
    ↓
调用transferTo()或getInputStream()处理文件

基本上传Controller

Java
@RestController
@RequestMapping("/api/upload")
public class UploadController {

    @PostMapping("/single")
    public String upload(@RequestParam("file") MultipartFile file) {
        if (file.isEmpty()) {
            throw new IllegalArgumentException("文件为空");
        }

        String fileName = file.getOriginalFilename();
        String filePath = "/upload/" + UUID.randomUUID() + getExtension(fileName);

        try {
            file.transferTo(new File(filePath));
            return "上传成功: " + fileName;
        } catch (IOException e) {
            throw new RuntimeException("上传失败", e);
        }
    }

    private String getExtension(String fileName) {
        return fileName != null && fileName.contains(".")
            ? fileName.substring(fileName.lastIndexOf("."))
            : "";
    }
}

Servlet 3.0注册配置

YAML
@Configuration
public class WebConfig {

    @Bean
    public MultipartConfigElement multipartConfigElement() {
        MultipartConfigFactory factory = new MultipartConfigFactory();
        factory.setMaxFileSize(DataSize.ofMegabytes(10));
        factory.setMaxRequestSize(DataSize.ofMegabytes(100));
        factory.setFileSizeThreshold(DataSize.ofKilobytes(2));
        factory.setLocation("/tmp/upload");
        return factory.createMultipartConfig();
    }

    @Bean
    public ServletRegistrationBean<DispatcherServlet> dispatcherServletRegistration(
            DispatcherServlet dispatcherServlet,
            MultipartConfigElement multipartConfig) {

        ServletRegistrationBean<DispatcherServlet> registration =
            new ServletRegistrationBean<>(dispatcherServlet, "/");
        registration.setMultipartConfig(multipartConfig);
        return registration;
    }
}

CommonsMultipartResolver(旧版)

Spring 3.x时代使用Commons FileUpload:

Java
@Bean
public MultipartResolver multipartResolver() {
    CommonsMultipartResolver resolver = new CommonsMultipartResolver();
    resolver.setMaxUploadSize(10 * 1024 * 1024);       // 10MB
    resolver.setMaxInMemorySize(2 * 1024);             // 2KB
    resolver.setDefaultEncoding("UTF-8");
    resolver.setUploadTempDir(new FileSystemResource("/tmp/upload"));
    return resolver;
}

现推荐使用StandardServletMultipartResolver,无需额外依赖。

内存阈值作用

threshold值行为
0所有文件写入临时目录
小于文件大小超过threshold的写入临时目录
大于文件大小文件保留在内存中
YAML
spring:
  servlet:
    multipart:
      file-size-threshold: 2KB
  • 文件小于2KB:保留在内存中
  • 文件大于2KB:写入临时文件

临时文件清理

HTML
@Configuration
public class MultipartCleanupConfig {

    @Bean
    public MultipartFilter multipartFilter() {
        return new MultipartFilter();
    }
}

Spring自动清理临时文件,无需手动处理。

延迟解析

JavaScript
spring:
  servlet:
    multipart:
      resolve-lazily: true
  • false:请求到达立即解析multipart
  • true:实际需要时才解析multipart

延迟解析可节省内存,但可能导致异常时机不一致。

文件上传表单

Java
<form action="/api/upload" method="post" enctype="multipart/form-data">
    <input type="file" name="file">
    <button type="submit">上传</button>
</form>

enctype必须设置为multipart/form-data。

AJAX上传

text
function uploadFile(file) {
    const formData = new FormData();
    formData.append('file', file);

    fetch('/api/upload', {
        method: 'POST',
        body: formData
    });
}

// 不设置Content-Type,浏览器自动设置multipart/form-data

MultipartFile常用方法

text
@PostMapping("/info")
public Map<String, Object> fileInfo(@RequestParam("file") MultipartFile file) {
    Map<String, Object> info = new HashMap<>();

    info.put("name", file.getName());              // 表单参数名
    info.put("originalName", file.getOriginalFilename());  // 原始文件名
    info.put("contentType", file.getContentType());
    info.put("size", file.getSize());              // 字节数
    info.put("sizeKB", file.getSize() / 1024);
    info.put("sizeMB", file.getSize() / 1024 / 1024);
    info.put("empty", file.isEmpty());

    return info;
}

要点总结

  • multipart/form-data是文件上传的标准格式
  • StandardServletMultipartResolver是默认解析器
  • max-file-size限制单文件大小
  • max-request-size限制总请求大小
  • file-size-threshold决定内存或临时文件存储
  • MultipartFile接口提供文件操作方法

📝 发现内容有误?点击此处直接编辑

← 上一篇 Spring MVC 异常处理与国际化
下一篇 → Spring MVC 文件下载实现
想查看更多题目和详细解析?
小程序提供完整的题库、模拟考试和详细解析
马上就来

长按或扫描二维码,立即体验

扫码体验小程序
马上就来
使用微信扫描二维码
立即体验完整题库