原文链接:使用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接口实现文件上传的改造点
一般的文件上传接口定义:
@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);这里注意两点:
在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));
}现在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获取文件的实际类型 引入
需要注意以下几点
END.
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。