【轉載】使用Feign接口實現文件上傳的解決方案

原文鏈接:使用Feign接口實現文件上傳的解決方案

一般的情況下,後端有個微服務,暴露出一個文件上傳的restful接口給前端,前端調用該接口獲取上傳後的鏈接以及oss key值完成上傳。假設提供restful接口的這個服務叫做A,現在有個微服務B有個本地文件,需要將本地文件調用A文件文件上傳接口上傳到文件服務器,該如何做?

一般情況下,一個文件上傳的restful接口如下所示:

@PostMapping("/upload")
public WrapperResult<UploadResult> uploadFile(@RequestParam("file") MultipartFile multipartFile){
    ......
}

那對應的Feign接口就如下所示

@PostMapping("/upload")
public WrapperResult<UploadResult> uploadFile(@RequestParam("file") MultipartFile multipartFile);

從直覺上來看,直接調用八成會出問題(笑),通過踩坑,我梳理了下後端調用Feign接口實現文件上傳的改造點

1. 接口修改

一般的文件上傳接口定義:

@PostMapping("/upload")
public WrapperResult<UploadResult> uploadFile(@RequestParam("file") MultipartFile multipartFile){
    ......
}

在Feign接口暴露出來的情況下,則不能再使用@RequestParam註解,應當使用@RequestPart註解,另外需要指定consumes類型爲表單類型,否則會翻車。

修改後的接口如下

 @PostMapping(
    value = {"/upload"},
    consumes = {"multipart/form-data"}
)
UploadResult uploadFile(@RequestPart("file") @NotNull MultipartFile multipartFile);

這裏注意兩點:

  1. 使用@RequestPart註解替換掉@RequestParam註解
  2. 指定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);
}

返回了一個SpringEncoder對象,這裏需要返回一個SpringFormEncoder對象以支持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. 客戶端調用修改

現在Feign接口長這個樣子

 @PostMapping(
    value = {"/upload"},
    consumes = {"multipart/form-data"}
)
UploadResult uploadFile(@RequestPart("file") @NotNull MultipartFile multipartFile);

那我們Feign接口調用的時候就得構造MultipartFile對象,這裏需要引入spring-test的依賴

<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-test</artifactId>
</dependency>

然後代碼這麼寫

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,關於tika,參考文章 使用tika獲取文件的實際類型 引入

需要注意以下幾點

  1. 需要引入spring-test,注意scope默認就行,不能爲provided
  2. 需要引入tika,告知正確的媒體類型,否則上傳到minio等文件服務器,在瀏覽器中打開圖片、mp4視頻等文件本來應當在瀏覽器打開的文件會變成自動下載

最後,歡飲關注我的博客:一枝梅的博客

END.

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章