原文鏈接:使用Feign接口實(shí)現(xiàn)文件上傳的解決方案
一般的情況下,后端有個(gè)微服務(wù),暴露出一個(gè)文件上傳的restful接口給前端,前端調(diào)用該接口獲取上傳后的鏈接以及oss key值完成上傳从橘。假設(shè)提供restful接口的這個(gè)服務(wù)叫做A,現(xiàn)在有個(gè)微服務(wù)B有個(gè)本地文件,需要將本地文件調(diào)用A文件文件上傳接口上傳到文件服務(wù)器派继,該如何做宾袜?
一般情況下,一個(gè)文件上傳的restful接口如下所示:
@PostMapping("/upload")
public WrapperResult<UploadResult> uploadFile(@RequestParam("file") MultipartFile multipartFile){
......
}
那對(duì)應(yīng)的Feign接口就如下所示
@PostMapping("/upload")
public WrapperResult<UploadResult> uploadFile(@RequestParam("file") MultipartFile multipartFile);
從直覺(jué)上來(lái)看互艾,直接調(diào)用八成會(huì)出問(wèn)題(笑)试和,通過(guò)踩坑,我梳理了下后端調(diào)用Feign接口實(shí)現(xiàn)文件上傳的改造點(diǎn)
1. 接口修改
一般的文件上傳接口定義:
@PostMapping("/upload")
public WrapperResult<UploadResult> uploadFile(@RequestParam("file") MultipartFile multipartFile){
......
}
在Feign接口暴露出來(lái)的情況下纫普,則不能再使用@RequestParam注解阅悍,應(yīng)當(dāng)使用@RequestPart注解,另外需要指定consumes類型為表單類型昨稼,否則會(huì)翻車(chē)节视。
修改后的接口如下
@PostMapping(
value = {"/upload"},
consumes = {"multipart/form-data"}
)
UploadResult uploadFile(@RequestPart("file") @NotNull MultipartFile multipartFile);
這里注意兩點(diǎn):
- 使用@RequestPart注解替換掉@RequestParam注解
- 指定consumes類型為表單類型
2. Encoder修改
在springboot中,一般的Encoder定義如下
@Bean
@Primary
public Encoder feignEncoder() {
HttpMessageConverter jacksonConverter = new MappingJackson2HttpMessageConverter(
JsonUtils.getObjectMapper()
);
ObjectFactory<HttpMessageConverters> objectFactory =
() -> new HttpMessageConverters(jacksonConverter);
return new SpringEncoder(objectFactory);
}
返回了一個(gè)SpringEncoder對(duì)象假栓,這里需要返回一個(gè)SpringFormEncoder對(duì)象以支持Feign接口的表單功能寻行,只需要將new SpringEncoder(objectFactory)修改為new SpringFormEncoder(new SpringEncoder(objectFactory))即可,修改后的代碼如下
@Bean
@Primary
public Encoder feignEncoder() {
HttpMessageConverter jacksonConverter = new MappingJackson2HttpMessageConverter(
JsonUtils.getObjectMapper()
);
ObjectFactory<HttpMessageConverters> objectFactory =
() -> new HttpMessageConverters(jacksonConverter);
return new SpringFormEncoder(new SpringEncoder(objectFactory));
}
3. 客戶端調(diào)用修改
現(xiàn)在Feign接口長(zhǎng)這個(gè)樣子
@PostMapping(
value = {"/upload"},
consumes = {"multipart/form-data"}
)
UploadResult uploadFile(@RequestPart("file") @NotNull MultipartFile multipartFile);
那我們Feign接口調(diào)用的時(shí)候就得構(gòu)造MultipartFile對(duì)象匾荆,這里需要引入spring-test的依賴
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-test</artifactId>
</dependency>
然后代碼這么寫(xiě)
FileInputStream fis = null;
try {
Tika tika = new Tika();
String mimeType = tika.detect(file);
fis = new FileInputStream(file);
MockMultipartFile mockMultipartFile = new MockMultipartFile(
"file",
file.getName(),
mimeType,
fis
);
UploadResult uploadResult = ossPublicApi.uploadFile(mockMultipartFile);
}catch(Exception e){
......
}
這里為了告知正確的媒體類型拌蜘,引入了tika,關(guān)于tika牙丽,參考文章 使用tika獲取文件的實(shí)際類型 引入
需要注意以下幾點(diǎn)
- 需要引入spring-test简卧,注意scope默認(rèn)就行,不能為provided
- 需要引入tika烤芦,告知正確的媒體類型举娩,否則上傳到minio等文件服務(wù)器,在瀏覽器中打開(kāi)圖片构罗、mp4視頻等文件本來(lái)應(yīng)當(dāng)在瀏覽器打開(kāi)的文件會(huì)變成自動(dòng)下載
END.