上期《编写接口的正确姿势》讲了SpringBoot接口入参及定义的规范,有朋友问“带有附件的接口应如何处理呢?”借着这个机会,我们一起再重温一下。 本期除了文件入参,还有 @ModelAttribute 的干货嗷
SpringBoot配置
在 Spring Boot 中处理文件上传,需先配置 Multipart 文件解析器。在 application.properties 中添加以下配置:
# 单个文件最大大小(默认1MB)
spring.servlet.multipart.max-file-size=10MB
# 单个请求最大总大小(默认10MB)
spring.servlet.multipart.max-request-size=50MB
# 是否延迟解析(大文件建议开启)
spring.servlet.multipart.resolve-lazily=true
如何写入参
单文件上传
使用 MultipartFile file 进行入参接收即可
@RestController
public class FileUploadController {
@PostMapping("/upload")
public String uploadFile(@RequestParam("file") MultipartFile file) {
if (file.isEmpty()) {
return "文件不能为空";
}
// 处理文件存储逻辑
return "上传成功";
}
}
多文件上传
使用 MultipartFile[] file 或者 List<MultipartFile> files 都可
@PostMapping("/multiUpload")
public String multiUpload(@RequestParam("files") MultipartFile[] files) {
Arrays.stream(files).forEach(file -> {
// 循环处理每个文件
});
return "批量上传成功";
}
与其它参数一起入参?
独立参数
当 file 和 meta 无逻辑关联时,我们可以使用 @RequestPart 进行文件和实体类的同时接收
@PostMapping(value = "/uploadWithMeta", consumes = MediaType.MULTIPART_FORM_DATA_VALUE)
public String uploadWithMetadata(
@RequestPart("file") MultipartFile file,
@RequestPart("meta") @Valid FileMeta meta) {
// 同时处理文件和元数据
return "上传成功";
}
RequestPart 详解
| 注解 | 适用场景 | 示例 |
|---|---|---|
@RequestParam | 简单表单上传(键值对+文件) | @RequestParam("file") MultipartFile file |
@RequestPart | 复杂请求体(如混合JSON和文件) | @RequestPart("metadata") MetaData data, @RequestPart("file") MultipartFile file |
混合参数
当 file 和 meta 逻辑关联紧密时(例如自定义文件名称),可以通过带有 MultipartFile 的实体类进行入参
@Data
public class FileEntity {
private String name;
private MultipartFile multipartFile;
}
但这时候问题来了,使用 @RequestBody 接收参数,竟然报 multipartFile 为 null 值
@PostMapping("/upload")
public String uploadFile(@RequestBody FileEntity fileEntity) {
String fileName = fileEntity.getName();
MultipartFile file = fileEntity.getMultipartFile();
// 处理业务逻辑
return "上传成功";
}
经过验证,我发现省略 @RequestBody,直接使用缺省的 FileEntity 接收竟然成功了,这里就不得不引出 @ModelAttribute 了
public String uploadFile(FileEntity fileEntity)
@ModelAttribute 和 @RequestBody
- @RequestBody:用于解析 JSON/XML 请求体,无法处理
multipart/form-data格式,也就是我们熟悉的application/json。 - @ModelAttribute:专为表单数据设计,支持混合普通字段与文件字段。
当我们需要 file 和 meta 混合接收时,前端传参格式应为 multipart/form-data,此时我们应使用 @ModelAttribute 进行入参接收,即可既拿到文件又拿到普通字段了。
那么问题又来了,我上面没有使用 @ModelAttribute,而是缺省了入参注解,为什么也能接受呢?
@ModelAttribute 缺省
在某些情况下,我们的入参注解是可以缺省的,以下举例:
-
传参格式为 multipart/form-data
当请求体是
multipart/form-data格式(即表单上传文件)时,Spring Boot 会自动将表单字段绑定到入参对象(如FileEntity),此时可以省略@ModelAttribute。@PostMapping("/upload") public String uploadFile(FileEntity fileEntity) { // 省略 @RequestBody return "上传成功: " + fileEntity.getName(); } -
传参格式为 query parameters
对于 GET 请求,Spring Boot 会自动将查询参数绑定到方法入参对象(如
User),此时可以省略@RequestBody。@GetMapping("/user") public String getUser(User user) { // 省略 @RequestBody return "用户信息: " + user.getName() + ", " + user.getAge(); }前端传参:
http://localhost:8080/user?name=John&age=25 -
传参格式为 application/json,不可缺省
对于
application/json格式的请求,Spring Boot 不会自动将请求体绑定到方法入参对象,必须显式使用@RequestBody。@PostMapping("/createUser") public String createUser(@RequestBody User user) { // 必须使用 @RequestBody return "创建用户: " + user.getName(); } -
传参格式为 application/xml,不可缺省
对于
application/xml格式的请求,Spring Boot 不会自动将请求体绑定到方法入参对象,必须显式使用@RequestBody。
即使可以省略 @RequestBody,也建议显式添加注解以提高代码可读性,不要像笔者一样有缺省的坏习惯~
所以我在 "混合参数" 时缺省了注解,也依然是使用了 @ModelAttribute 进行了实体类的接收,此时是可以正常完成接收的。
总结
本次我们聊了聊 Spring Boot 在写文件上传接口时,应怎样更好地入参,那么对于文件上传,安全策略、文件校验、分片上传也是我们应该掌握的,下期我们再聊吧~
好看记得关注嗷~