文章目录
- 方法参数
- 单文件上传
-
- [1. MultipartFile 的 transferTo(File dest)](#1. MultipartFile 的 transferTo(File dest))
- [2. MultipartFile 的 transferTo(Path dest)](#2. MultipartFile 的 transferTo(Path dest))
- [3. MultipartFile + Files.write(Path path, byte[] bytes, OpenOption... options)](#3. MultipartFile + Files.write(Path path, byte[] bytes, OpenOption... options))
- [4. MultipartFile + Files.copy(InputStream in, Path target, CopyOption... options)](#4. MultipartFile + Files.copy(InputStream in, Path target, CopyOption... options))
- [5. HttpServletRequest 的 getPart(String var1)](#5. HttpServletRequest 的 getPart(String var1))
- 多文件上传(兼容单文件)
-
- [1. MultipartFile[ ] + 前四种上传方法](#1. MultipartFile[ ] + 前四种上传方法)
- [2. List<MultipartFile> + 前四种上传方法](#2. List<MultipartFile> + 前四种上传方法)
- [3. MultipartHttpServletRequest + 前四种上传方法](#3. MultipartHttpServletRequest + 前四种上传方法)
- [4. HttpServletRequest 的 getParts()](#4. HttpServletRequest 的 getParts())
- 补充
- 总结
Win、JDK 17、 Spring Boot 3.1.2
方法参数
- Spring 的 MultipartFile(最常用)
- Spring 的 MultipartHttpServletRequest
- Servlet 的 HttpServletRequest(原生)
单文件上传
1. MultipartFile 的 transferTo(File dest)
java
@PostMapping("/upload-1")
public String upload1(@RequestPart("file") MultipartFile mf) throws IOException {
String filename = mf.getOriginalFilename();
mf.transferTo(new File("d:/", filename));
return "upload success";
}
2. MultipartFile 的 transferTo(Path dest)
java
@PostMapping("/upload-2")
public String upload2(@RequestParam("file") MultipartFile mf) throws IOException {
String filename = mf.getOriginalFilename();
Path path = Paths.get("upload", filename);
mf.transferTo(path);
return "upload success";
}
3. MultipartFile + Files.write(Path path, byte[] bytes, OpenOption... options)
java
@PostMapping("/upload-3")
public String upload3(@RequestParam("file") MultipartFile mf) throws IOException {
String filename = mf.getOriginalFilename();
Path path = Paths.get("upload", filename);
Files.write(path, mf.getBytes());
return "upload success";
}
4. MultipartFile + Files.copy(InputStream in, Path target, CopyOption... options)
java
@PostMapping("/upload-4")
public String upload4(@RequestParam("file") MultipartFile mf) throws IOException {
String filename = mf.getOriginalFilename();
Path path = Paths.get("upload", filename);
// 若文件已存在,则会抛出 FileAlreadyExistsException
Files.copy(mf.getInputStream(), path);
return "upload success";
}
5. HttpServletRequest 的 getPart(String var1)
java
public String upload8(HttpServletRequest req) throws ServletException, IOException {
// 获取上传的文件流,单文件
Part filePart = req.getPart("file");
String filename = filePart.getSubmittedFileName();
// 构建目标文件对象
Path path = Paths.get("upload", filename);
byte[] bytes = filePart.getInputStream().readAllBytes();
InputStream in = filePart.getInputStream();
// Files.write(path, bytes);
// Files.copy(in,path);
return "upload success";
}
多文件上传(兼容单文件)
1. MultipartFile[ ] + 前四种上传方法
java
@PostMapping("/upload-5")
public String upload5(@RequestParam("files") MultipartFile[] files) {
for (MultipartFile mf : files) {
// 同理又有四种
// mf.transferTo(File dest)
// mf.transferTo(Path dest)
// Files.write(Path path, byte[] bytes, OpenOption... options)
// Files.copy(mf.getInputStream(), path);
}
return "upload success";
}
2. List<MultipartFile> + 前四种上传方法
java
@PostMapping("/upload-6")
public String upload6(@RequestParam("files") List<MultipartFile> files) {
for (MultipartFile mf : files) {
// 同理又有四种
// mf.transferTo(File dest)
// mf.transferTo(Path dest)
// Files.write(Path path, byte[] bytes, OpenOption... options)
// Files.copy(mf.getInputStream(), path);
}
return "upload success";
}
3. MultipartHttpServletRequest + 前四种上传方法
java
@PostMapping("/upload-7")
public String upload7(MultipartHttpServletRequest req) {
req.getFileNames().forEachRemaining(name -> {
for (MultipartFile mf : req.getFiles(name)) {
// 同理又有四种
// mf.transferTo(File dest)
// mf.transferTo(Path dest)
// Files.write(Path path, byte[] bytes, OpenOption... options)
// Files.copy(mf.getInputStream(), path);
}
});
return "upload success";
}
4. HttpServletRequest 的 getParts()
java
@PostMapping("/upload-9")
public String upload9(HttpServletRequest req) throws ServletException, IOException {
Collection<Part> parts = req.getParts();
for (Part part : parts) {
String filename = part.getSubmittedFileName();
Path path = Paths.get("upload", filename);
byte[] bytes = part.getInputStream().readAllBytes();
InputStream in = part.getInputStream();
// Files.write(path, bytes);
// Files.copy(in,path);
}
return "upload success";
}
补充
以上方法仅为示例代码,注意 NPE
以上方法仅适用于小文件上传,不适合上百 MB 的大文件上传
Files.copy() 无法覆盖文件,会抛异常
@RequestPart 可替代 @RequestParam
@RequestParam
和 @RequestPart
都是Spring框架中用于处理HTTP请求参数的注解,但它们在处理文件上传时有一些区别。
-
@RequestParam:
- 用于处理普通的表单字段和查询参数,适用于处理常规的请求参数。
- 在处理文件上传时,可以用于接收文件的元数据(如文件名、大小等),但无法直接获取文件的内容。
- 对于文件上传,
@RequestParam
需要配合MultipartFile
类型参数来获取文件的内容。
示例:
java@PostMapping("/upload") public String handleFileUpload(@RequestParam("file") MultipartFile file) { // 处理文件上传逻辑 // ... }
-
@RequestPart:
- 用于处理文件上传请求,特别适用于处理发送
multipart/form-data
类型的请求。 - 允许直接获取文件的内容,不需要再额外使用
MultipartFile
类型参数来获取文件内容。 - 可以用于接收文件的元数据(如文件名、大小等),也可以直接获取文件的字节流。
示例:
java@PostMapping("/upload") public String handleFileUpload(@RequestPart("file") byte[] fileBytes, @RequestPart("file") InputStream fileInputStream, @RequestPart("file") Part filePart) { // 处理文件上传逻辑 // ... }
- 用于处理文件上传请求,特别适用于处理发送
综上所述,@RequestParam
用于处理常规的请求参数和文件元数据,需要额外使用 MultipartFile
类型参数来获取文件内容。而 @RequestPart
则更适用于处理文件上传请求,允许直接获取文件的内容,并且可以用于接收文件元数据。
在实际使用中,你可以根据请求的具体内容和需求来选择合适的注解,以及结合相应的处理方式。如果仅处理文件上传,使用 @RequestPart
更为直接方便;如果需要处理普通请求参数和文件上传一起,可以使用 @RequestParam
来处理。
总结
Spring MVC 提供了多种方法来处理文件上传,开发者可以根据项目需求和性能考虑选择适合的方法。对于小文件上传,使用 MultipartFile 接口是简单有效的选择。
无论选择哪种方法,都应该注意文件上传过程中的安全性和性能,避免潜在的漏洞和性能问题。合理设置文件大小限制,处理异常情况,以及对文件上传进行必要的验证和授权,都是保障文件上传功能正常运作的重要因素。