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 的区别

对比项MultipartFileFile
来源Spring MVCJava 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 后端面试中的常见考点。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值