深浅模式
文件上传,就是把本地的图片、音频、视频等文件,通过前端页面发送到服务器,方便后续的存储和访问。
要实现这样一个功能,本质上只需要三个环节:
- 前端:构建能正确提交文件的页面;
- 后端:编写接口接收并处理文件;
- 存储:把接收到的文件保存到本地或云端。
前端与后端各有关键要素,而存储实现上,我们会分别实现 本地上传 和 OSS 云存储 两种方式。
前端传递
文件上传的前端实现,关键只要三样到位:
- 必须使用
type="file"
的控件,这样用户才能从本地选择文件。 - 请求方式必须是
POST
,因为GET
请求无法承载二进制文件内容。 enctype
必须设置为multipart/form-data
,否则后端根本收不到文件。
一个最基础的上传表单示例 👇
html
<form action="/upload" method="post" enctype="multipart/form-data">
名字:<input type="text" name="userName"><br>
年龄:<input type="text" name="userAge"><br>
头像:<input type="file" name="avatar"><br>
<input type="submit" value="提交">
</form>
选中文件后,浏览器会在提交时将文本字段与文件内容一并打包发送给后端。
只要这三件事做到位,后端接口就能顺利接收到文件。
后端接收
前端表单提交之后,后端必须有一个接口能把这份请求“接住”。
在 Spring Boot 里,处理文件上传最常用的方式就是使用 MultipartFile
。它不仅能接收文件本身,也能同时接收普通的文本字段
java
@RestController
public class UploadController {
@PostMapping("/upload")
public Result upload(String userName, Integer userAge, MultipartFile avatar) {
log.info("收到上传请求:名字 = {}, 年龄 = {}, 文件 = {}", userName, userAge, avatar);
return Result.success();
}
}
这里的 MultipartFile
会自动映射前端上传的文件内容。
参数名必须和前端的 name
属性保持一致,比如表单中是 avatar
,方法参数也得是 avatar
,否则就接收不到。
这样,一个最简单的“上传请求”闭环就打通了。
本地存储
文件上传到后端后,如果只是为了让服务器本身能读取和访问这些文件,最简单的方式就是直接存到本地磁盘。
Spring Boot 已经为我们封装好了常用方法,MultipartFile
提供的 transferTo()
就能把上传的文件保存下来:
java
@PostMapping("/upload")
public Result upload(String userName, Integer userAge, MultipartFile avatar) throws Exception {
// 获取原始文件名,然后截取文件后缀
String originalFilename = avatar.getOriginalFilename(); // 例如:001.jpg
String suffix = originalFilename.substring(originalFilename.lastIndexOf(".")); // .jpg
// 生成随机文件名,避免覆盖
String newFileName = UUID.randomUUID().toString() + suffix;
// 构建存储路径(这里用 D 盘举例)
File dest = new File("D:/upload_test/" + newFileName);
// 6. 保存文件
avatar.transferTo(dest);
return Result.success("文件已保存:" + dest.getAbsolutePath());
}
这段代码的核心就两步:
- 获取文件原始信息(名字、后缀);
- 转成新文件名然后
transferTo()
存进去。
如果你直接用原始名称存,多个用户上传同名文件时会互相覆盖,所以实际开发中都会用 UUID
生成一个唯一的名字,再拼上原始的后缀。
上传大小限制
Spring Boot 默认的单文件上传大小只有 1MB,如果超了,就会直接报错,例如:
The field avatar exceeds its maximum permitted size of 1048576 bytes.
解决方式很简单,只要在 application.properties
里改配置就行:
properties
# 单个文件最大 10MB
spring.servlet.multipart.max-file-size=10MB
# 单次请求最大 100MB(比如一次上传多个文件)
spring.servlet.multipart.max-request-size=100MB
配置好后,transferTo()
就能轻松保存更大的文件了。
云端存储:传到 OSS
在项目部署到云服务器后,本地磁盘存文件就不太合适了:
用 阿里云 OSS 这种对象存储服务会更合适。它本质上就是一个更稳定、更安全的“远程文件仓库”,可以随时上传、下载、外链访问。
实现流程和本地存储几乎一样,区别只在于最后这一步不再是 transferTo()
,而是通过 OSS SDK 把文件流上传到云端。
典型步骤如下 👇
- 申请 AccessKey(用来授权访问 OSS);
- 创建 Bucket(相当于一个文件夹);
- 使用 SDK 上传文件流;
- 返回文件的公网访问地址。
代码结构示例 👇
java
// 生成唯一文件名
String originalFilename = avatar.getOriginalFilename();
String suffix = originalFilename.substring(originalFilename.lastIndexOf("."));
String newFileName = UUID.randomUUID().toString() + suffix;
// 上传到 OSS
String fileUrl = ossClient.putObject(bucketName, newFileName, avatar.getInputStream());
// 返回外链
return Result.success(fileUrl);
这样一来,文件就不会再依赖本地磁盘,而是被存进云端。
只要有外链,任何人都能直接访问这份文件,不用占用你的服务器空间。
评论