Spring Boot文件上傳五種玩法!@RequestPart最強大
環境:SpringBoot3.4.2
1. 簡介
在Spring Boot中,文件上傳的實現非常簡單且高效,開發者可以快速集成這一常見功能。通過Spring MVC提供的MultipartFile接口,配合@RequestParam注解,只需幾行代碼即可完成文件接收。
本篇文章我們將介紹當我們的接口涉及到文件上傳時個各種玩法。
2. 實戰案例
2.1 基本應用
@PostMapping("/form")
public String handleFormUpload(
@RequestParam("name") String name,
@RequestParam("file") MultipartFile file) throws Exception {
if (!file.isEmpty()) {
file.transferTo(new File("d:\\upload\\" + file.getOriginalFilename())) ;
return "success" ;
}
return "failure" ;
}
這里MultipartFile類型參數也可以不使用@RequestParam("file"),不過這就需要你上傳文件是的name屬性值域你的這里變量名一致。
將參數類型聲明為 List<MultipartFile> 時,可解析同名參數名下的多個文件(即客戶端通過同一表單字段名上傳多個文件時,會以列表形式綁定到方法參數)。
2.2 使用Map接收文件
@PostMapping("/map")
public String handleMapUpload(
@RequestParam("name") String name,
@RequestParam Map<String, MultipartFile> files) throws Exception {
files.forEach((key, file) -> {
System.out.println("name = " + key) ;
try {
file.transferTo(new File("d:\\upload\\" + file.getOriginalFilename())) ;
}
}) ;
return "success" ;
}
當使用 @RequestParam 注解并聲明參數類型為 Map<String, MultipartFile> 或 MultiValueMap<String, MultipartFile>,且注解中未指定參數名(即不通過 value/name 屬性顯式命名)時,該映射結構將自動填充所有上傳的 multipart 文件,其中鍵為表單字段名(每個字段名可能對應多個文件),值為對應字段名下的文件集合。
圖片
輸出結果
name = file1
name = file2
2.3 封裝為對象
你還可以將 multipart 內容作為數據綁定的一部分,綁定到命令對象(Command Object)上。例如,上面示例中的表單字段和文件均可作為表單對象(DataForm)的屬性。
@PostMapping("/dataform")
public String handleDateFormUpload(DataForm form) throws Exception {
System.err.println("name = " + form.getName()) ;
MultipartFile file = form.getFile();
file.transferTo(new File("d:\\upload\\" + file.getOriginalFilename())) ;
return "success" ;
}
// DataForm對象定義
public class DataForm {
private String name ;
private MultipartFile file ;
}
圖片
2.4 使用Part接收
在使用 Servlet 的多部分(multipart)解析功能時,你也可將 jakarta.servlet.http.Part 接口(而非 Spring 的 MultipartFile)聲明為方法參數或集合值類型。
@PostMapping("/part")
public String handlePartUpload(
@RequestParam("name") Part name,
@RequestParam Part file) throws Exception {
String value = StreamUtils.copyToString(name.getInputStream(), StandardCharsets.UTF_8) ;
System.err.println("name = " + value) ;
name.getHeaderNames().forEach(key -> System.out.println(name.getHeader(key))) ;
System.err.println("-------------------------") ;
FileOutputStream out = new FileOutputStream(new File("d:\\upload\\" + file.getSubmittedFileName()));
StreamUtils.copy(file.getInputStream(), out) ;
file.getHeaderNames().forEach(key -> System.out.println(file.getHeader(key))) ;
out.close() ;
}
注意,這里我們將普通字段,也通過Part接口來接收。輸出結果如下:
圖片
通過控制臺查看如下:
圖片
2.5 使用@RequestPart注解
當我們還需要接收json 數據時(類似@RequestBody)。此時可使用 @RequestPart 注解,在通過 HttpMessageConverter 轉換后訪問多部分(multipart)數據。
@PostMapping("/requestpart")
public Object requestpart(
@RequestPart("user") User user,
@RequestPart("file") MultipartFile file
) throws Exception {
file.transferTo(new File("d:\\upload\\" + file.getOriginalFilename())) ;
return user ;
}
前端代碼如下:
let form = new FormData()
// 文件附件
form.append('file', document.querySelector('#file').files[0])
let data = {age: 5000, name: '中國????'}
// 通過Blob來構建一個不可變、原始數據的類文件對象,同時指明你數據類型
let user = new Blob([JSON.stringify(data)], { type: 'application/json' })
form.append('user', user)
axios({
method: 'post',
url: 'http://localhost:8080/api/request/requestpart',
// 設置請求header,這里設置multipart/mixed也可以
headers: {
'Content-Type': 'multipart/form-data'
},
data: form
})
每一個表單項都設置了不同的type類型,這樣我們的后臺接口就會根據具體的類型進行數據的轉換。
圖片
對于上面的 User 類型參數,我們還可以使用@Valid進行參數校驗。
public Object requestpart(
@Valid @RequestPart("user") User user,
@RequestPart("file") MultipartFile file) {}
這樣我們就可以對User實體屬性進行校驗了。