Spring Boot 文件上传详解:深入理解 MultipartFile 的使用与原理

在 Java Web 开发中,文件上传是一项非常常见的需求,例如上传头像、Excel 文件、图片、PDF、视频等。Spring MVC 为我们提供了 MultipartFile 接口,使文件上传变得十分简单。本文将从原理、常用 API、实际开发、注意事项以及面试角度,全面介绍 MultipartFile


一、什么是 MultipartFile?

MultipartFile 是 Spring MVC 提供的一个接口,用于接收客户端上传的文件。

当前端通过 <input type="file"> 上传文件时,浏览器会采用 multipart/form-data 编码格式发送 HTTP 请求,SpringMVC 会自动解析请求,并封装成 MultipartFile 对象。

也就是说:

MultipartFile 本质上就是 SpringMVC 对上传文件的一层封装。

开发者无需自己解析 HTTP 请求体,只需要接收 MultipartFile 即可。

例如:

复制代码
@PostMapping("/upload")
public String upload(MultipartFile file){
    return "success";
}

Spring 会自动完成以下工作:

  1. 接收 HTTP 请求

  2. 解析 multipart/form-data

  3. 提取上传文件

  4. 封装成 MultipartFile

  5. 注入到 Controller 方法参数

整个过程开发者几乎无需额外处理。


二、文件上传流程

一次文件上传通常经历以下几个步骤:

复制代码
浏览器
    │
    │ 选择文件
    ▼
multipart/form-data 请求
    │
    ▼
DispatcherServlet
    │
    ▼
MultipartResolver
    │
    ▼
MultipartFile
    │
    ▼
Controller
    │
    ▼
保存到磁盘/数据库/OSS/MinIO

可以理解为:

浏览器负责发送文件。

SpringMVC 负责解析文件。

MultipartFile 负责保存文件信息。

开发者负责决定文件最终存放的位置。


三、Spring Boot 上传配置

Spring Boot 默认已经集成了文件上传功能,只需要配置上传大小即可。

复制代码
spring:
  servlet:
    multipart:
      enabled: true
      max-file-size: 10MB
      max-request-size: 20MB

参数说明:

配置项 说明
enabled 是否开启文件上传
max-file-size 单个文件最大大小
max-request-size 整个请求最大大小

例如:

一次上传:

复制代码
头像.jpg
2MB

允许上传。

如果上传:

复制代码
视频.mp4
50MB

则会抛出:

复制代码
MaxUploadSizeExceededException

四、MultipartFile 常用方法

Spring 提供了许多常用方法。

1、获取文件名

复制代码
String fileName = file.getOriginalFilename();

例如:

复制代码
photo.png

2、获取文件大小

复制代码
long size = file.getSize();

返回:

复制代码
204800

单位:

复制代码
Byte

3、获取文件类型

复制代码
String type = file.getContentType();

例如:

复制代码
image/png

image/jpeg

application/pdf

4、判断是否为空

复制代码
file.isEmpty();

开发中通常都会先判断:

复制代码
if(file.isEmpty()){
    return "文件不能为空";
}

5、获取输入流

复制代码
InputStream inputStream = file.getInputStream();

适用于:

  • 上传 OSS

  • 上传 MinIO

  • 上传七牛云

  • 上传腾讯 COS

因为这些云存储通常直接接收 InputStream。


6、保存文件

最常用的方法:

复制代码
file.transferTo(dest);

例如:

复制代码
File dest = new File("D:/upload/test.png");

file.transferTo(dest);

Spring 会自动完成文件复制。


五、实现单文件上传

Controller:

复制代码
@RestController
@RequestMapping("/file")
public class FileController {

    @PostMapping("/upload")
    public String upload(MultipartFile file) throws IOException {

        if(file.isEmpty()){
            return "文件为空";
        }

        File dir = new File("D:/upload");

        if(!dir.exists()){
            dir.mkdirs();
        }

        File dest = new File(dir,file.getOriginalFilename());

        file.transferTo(dest);

        return "上传成功";
    }

}

上传成功后:

复制代码
D:
    upload
        test.jpg

六、多文件上传

HTML:

复制代码
<input type="file" multiple>

Controller:

复制代码
@PostMapping("/uploads")
public String uploads(MultipartFile[] files) throws IOException {

    for (MultipartFile file : files) {

        if(file.isEmpty()){
            continue;
        }

        File dest = new File("D:/upload",file.getOriginalFilename());

        file.transferTo(dest);
    }

    return "success";
}

Spring 会自动封装多个文件。


七、防止文件重名

实际开发中不能直接使用原文件名。

例如:

用户 A:

复制代码
logo.png

用户 B:

复制代码
logo.png

第二次上传会覆盖第一次。

因此一般都会生成 UUID。

复制代码
String uuid = UUID.randomUUID().toString();

String suffix = file.getOriginalFilename()
                    .substring(file.getOriginalFilename().lastIndexOf("."));

String fileName = uuid + suffix;

生成:

复制代码
c9a22d1d-0b7d-4a31-a11d.png

这样可以避免文件名冲突。


八、文件类型校验

不能相信用户上传的数据。

例如:

有人可能把:

复制代码
病毒.exe

改成:

复制代码
图片.jpg

所以需要校验。

简单方式:

复制代码
String type = file.getContentType();

if(!type.startsWith("image/")){
    return "只能上传图片";
}

更严格的方式:

读取文件内容判断文件真实格式。

很多企业都会使用 Apache Tika 等工具进行检测。


九、文件大小校验

除了 Spring 配置限制。

代码里通常还会再次判断。

复制代码
if(file.getSize() > 5 * 1024 * 1024){
    return "文件不能超过5MB";
}

双重校验更加安全。


十、上传到服务器还是对象存储?

企业开发中一般有三种方式。

第一种:

保存到服务器本地。

复制代码
D:/upload

适用于:

  • 学习

  • 小项目

第二种:

保存到共享存储(NAS)。

多个服务器都可以访问。

第三种:

保存到对象存储。

例如:

  • 阿里云 OSS

  • MinIO

  • 腾讯云 COS

  • 七牛云 Kodo

这是目前企业最常见的方案。

优点:

  • 容量大

  • 支持 CDN

  • 支持权限控制

  • 便于扩容

  • 不占应用服务器磁盘


十一、MultipartFile 与 File 的区别

对比项 MultipartFile File
来源 Spring MVC Java IO
是否表示上传文件
是否依赖 Web 请求
是否能直接保存 可以 需要自己写流
使用场景 文件上传 本地文件操作

可以简单理解为:

  • MultipartFile 表示用户上传过程中的文件

  • File 表示服务器磁盘上的文件

在文件上传时,两者通常会配合使用:

复制代码
File dest = new File("D:/upload/test.png");

multipartFile.transferTo(dest);

MultipartFile 负责接收上传内容,File 负责表示保存目标。


十二、常见异常

1. 上传文件为空

原因:

未选择文件或上传失败。

解决:

复制代码
if(file.isEmpty()){
    return "请选择文件";
}

2. 文件超过限制

异常:

复制代码
MaxUploadSizeExceededException

解决:

调整 spring.servlet.multipart.max-file-sizemax-request-size 配置。


3. 保存路径不存在

原因:

目标目录未创建。

解决:

复制代码
File dir = new File("D:/upload");

if(!dir.exists()){
    dir.mkdirs();
}

4. 文件名为空

原因:

部分浏览器或客户端未正确传递文件名。

解决:

getOriginalFilename() 的返回值进行判空,并结合 UUID 生成新的文件名。


十三、面试高频问题

1. MultipartFile 是什么?

它是 Spring MVC 提供的文件上传接口,用于封装客户端上传的文件信息,开发者可以通过它获取文件名、大小、类型以及文件内容,并将文件保存到指定位置。

2. MultipartFileFile 有什么区别?

MultipartFile 表示 HTTP 请求中上传的文件,依赖于 Web 环境;File 是 Java IO 中表示文件或目录路径的对象,主要用于本地文件系统操作。

3. transferTo() 的作用是什么?

transferTo() 用于将上传文件保存到指定位置,底层会完成文件内容的写入,开发者无需手动编写输入输出流复制代码。

4. 为什么不能直接使用原文件名保存?

因为不同用户可能上传同名文件,直接保存会导致文件被覆盖。实际开发中通常使用 UUID、雪花算法或时间戳生成唯一文件名,并保留原始扩展名。

5. 企业项目中文件一般存在哪里?

大型项目通常不会将文件直接保存在应用服务器本地,而是存储到对象存储服务(如 OSS、MinIO、COS 等),既方便扩容,也便于结合 CDN 提升访问速度。


总结

MultipartFile 是 Spring MVC 文件上传功能的核心接口,它屏蔽了底层 HTTP 请求解析的复杂过程,使开发者能够专注于业务逻辑。实际开发中,一般会结合 UUID 防止文件重名、校验文件类型和大小,并根据项目规模选择本地存储或对象存储方案。掌握 MultipartFile 的使用流程和底层原理,不仅能够满足日常开发需求,也是 Java 后端面试中的常见考点。

相关推荐
其美杰布-富贵-李3 小时前
Spring Boot 工程开发全流程说明
java·spring boot·后端
qq_452396234 小时前
第二篇:《Go 开发环境搭建:SDK、IDE、Module 与 Hello World》
开发语言·ide·golang
天青色等烟雨..4 小时前
全流程ArcGISPro空间分析、三维建模、可视化及Python融合应用技术
开发语言·python
丰锋ff5 小时前
1.2 Qt常用基础类型
开发语言·qt
前端双越老师5 小时前
如何以前端视角(非0基础)学 Java ?
java·node.js·全栈
dear_bi_MyOnly5 小时前
【SpringBoot配置文件】
java·spring boot·后端·学习·spring·java-ee·学习方法
做个文艺程序员5 小时前
Linux第22篇:用Docker容器化你的Java SaaS应用:一次构建,随处运行
java·docker·容器
冰暮流星5 小时前
javascript之String方法介绍
开发语言·javascript·ecmascript
nianniannnn6 小时前
Qt QMessageBox知识点
开发语言·数据库·qt