Spring Boot文件上傳五種玩法!@RequestPart最強(qiáng)大
環(huán)境:SpringBoot3.4.2
1. 簡介
在Spring Boot中,文件上傳的實(shí)現(xiàn)非常簡單且高效,開發(fā)者可以快速集成這一常見功能。通過Spring MVC提供的MultipartFile接口,配合@RequestParam注解,只需幾行代碼即可完成文件接收。
本篇文章我們將介紹當(dāng)我們的接口涉及到文件上傳時(shí)個(gè)各種玩法。
2. 實(shí)戰(zhàn)案例
2.1 基本應(yīng)用
@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類型參數(shù)也可以不使用@RequestParam("file"),不過這就需要你上傳文件是的name屬性值域你的這里變量名一致。
將參數(shù)類型聲明為 List<MultipartFile> 時(shí),可解析同名參數(shù)名下的多個(gè)文件(即客戶端通過同一表單字段名上傳多個(gè)文件時(shí),會(huì)以列表形式綁定到方法參數(shù))。
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" ;
}
當(dāng)使用 @RequestParam 注解并聲明參數(shù)類型為 Map<String, MultipartFile> 或 MultiValueMap<String, MultipartFile>,且注解中未指定參數(shù)名(即不通過 value/name 屬性顯式命名)時(shí),該映射結(jié)構(gòu)將自動(dòng)填充所有上傳的 multipart 文件,其中鍵為表單字段名(每個(gè)字段名可能對應(yīng)多個(gè)文件),值為對應(yīng)字段名下的文件集合。
圖片
輸出結(jié)果
name = file1
name = file2
2.3 封裝為對象
你還可以將 multipart 內(nèi)容作為數(shù)據(jù)綁定的一部分,綁定到命令對象(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)解析功能時(shí),你也可將 jakarta.servlet.http.Part 接口(而非 Spring 的 MultipartFile)聲明為方法參數(shù)或集合值類型。
@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接口來接收。輸出結(jié)果如下:
圖片
通過控制臺(tái)查看如下:
圖片
2.5 使用@RequestPart注解
當(dāng)我們還需要接收json 數(shù)據(jù)時(shí)(類似@RequestBody)。此時(shí)可使用 @RequestPart 注解,在通過 HttpMessageConverter 轉(zhuǎn)換后訪問多部分(multipart)數(shù)據(jù)。
@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來構(gòu)建一個(gè)不可變、原始數(shù)據(jù)的類文件對象,同時(shí)指明你數(shù)據(jù)類型
let user = new Blob([JSON.stringify(data)], { type: 'application/json' })
form.append('user', user)
axios({
method: 'post',
url: 'http://localhost:8080/api/request/requestpart',
// 設(shè)置請求header,這里設(shè)置multipart/mixed也可以
headers: {
'Content-Type': 'multipart/form-data'
},
data: form
})
每一個(gè)表單項(xiàng)都設(shè)置了不同的type類型,這樣我們的后臺(tái)接口就會(huì)根據(jù)具體的類型進(jìn)行數(shù)據(jù)的轉(zhuǎn)換。
圖片
對于上面的 User 類型參數(shù),我們還可以使用@Valid進(jìn)行參數(shù)校驗(yàn)。
public Object requestpart(
@Valid @RequestPart("user") User user,
@RequestPart("file") MultipartFile file) {}
這樣我們就可以對User實(shí)體屬性進(jìn)行校驗(yàn)了。