Spring Cloud - FeignClient 上傳文件

Spring Cloud - FeignClient 上傳文件

場景

假設網站後臺(ServiceA)文件服務(ServiceB)報表服務(ServiceC)分別是三個不同的微服務,需要滿足如下兩個場景:

用戶通過ServiceA上傳頭像到ServiceB
ServiceC將生成的Excel二進制文件上傳到ServiceB

分析

J2EE架構網站一般通過Form Data上傳,然後通過MultipartFile來接收文件。FeignClient本身是不支持MultipartFile,需要通過額外的配置使其支持。Spring Cloud實現起來非常簡單。

步驟

Step 1.配置依賴

<dependency>
  <groupId>org.springframework.cloud</groupId>
  <artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>

一般這個依賴是現成的。

Step 2.註冊SpringFormEncoder

@Configuration
public class FeignMultipartSupportConfig {

    @Autowired
    private ObjectFactory<HttpMessageConverters> messageConverters;

    @Bean
    @Primary
    @Scope("prototype")
    public SpringFormEncoder multipartFormEncoder() {
        return new SpringFormEncoder(new SpringEncoder(messageConverters));
    }

    @Bean
    public feign.Logger.Level multipartLoggerLevel() {
        return feign.Logger.Level.FULL;
    }
}

關於異常class XXX is not a type supported by this encoder.,請務必在FeignMultipartSupportConfig中注入messageConverters!不要輕信百度出來的結果,使用Fein的原生註解前,不如先去看下源代碼。

Step 3.配置FeignClient

@FeignClient(
        value = "${msfile.name:msfile}",
        configuration = FeignMultipartSupportConfig.class)
public interface FileUploadFeignClient {

    @PostMapping(
            value = {"file/upload"},
            consumes = MediaType.MULTIPART_FORM_DATA_VALUE,
            produces = MediaType.APPLICATION_JSON_UTF8_VALUE
    )
    ResponseEntity<ResultFileUploadResp> upload(@RequestPart("file") MultipartFile file);

}

此處${msfile.name:msfile}是服務提供者的名字,consumes請配置成MediaType.MULTIPART_FORM_DATA_VALUE

這樣就可以解決場景一的需求,將文件從前端一直傳遞到文件服務器了。

Step 4.寫一個 File 轉 MultipartFile 的工具類

CommonsMultipartFile是MultipartFile的一個常用實現。

public class MultipartFileUtils {

    public static MultipartFile getMultipartFile(File file) {
        final DiskFileItem item = new DiskFileItem("file", MediaType.MULTIPART_FORM_DATA_VALUE, true, file.getName(), 1024 * 1024 * 1024, file.getParentFile());
        try {
            OutputStream os = item.getOutputStream();
            os.write(FileUtils.readFileToByteArray(file));
        } catch (IOException e) {
            e.printStackTrace(); // do nothing!
        }
        return new CommonsMultipartFile(item);
    }

}

將一個File對象封裝成MultipartFile參數,傳遞給FileUploadFeignClient的upload方法即可。文件名等會自動做URLEncoder。

PS. Spring Cloud版本爲Finchley.SR4,FileUtils來自Spring框架自帶的Commons IO組件。

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