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組件。