在项目上遇到了要用FeignClient传递文件MultipartFile的功能,在网上搜索了一圈,有好多方法,眼花缭乱,现在总结出尝试以后的几套方案供自己以后参考。
以下的所有方案中 composite是发送文件方, 接收文件方是客户端
我们所要做的操作都是在composite发送文件方的,背景是:
composite发送文件方:
注意需要添加 consumes = MediaType.MULTIPART_FORM_DATA_VALUE ,经测试发现,@RequestParam("multipartFile") MultipartFile multipartFile或者 @RequestPart("multipartFile") MultipartFile multipartFile,都可以成功调用,看来RequestPart并不是
public interface ICompositeOne {
@PostMapping("/One/uploadFile")
@ApiOperation(value = "上传文件---fegin的文件传递示例",notes = "上传文件---fegin的文件传递示例",tags = "OneAPI",
consumes = MediaType.MULTIPART_FORM_DATA_VALUE)
@ApiResponses(value = {@ApiResponse(code = 200,message = "成功"),
@ApiResponse(code = 500,message = "内部错误")})
boolean uploadFile(@RequestParam("multipartFile") MultipartFile multipartFile) throws Exception;
}
public class OneController implements ICompositeOne {
@Autowired
OneServiceClient oneServiceClient;
//composite的文件传输到客户端
@Override
public boolean uploadFile(MultipartFile multipartFile) throws Exception {
System.out.println("composite 层上传文件》》》");
return oneServiceClient.uploadFile(multipartFile);
}
}
接收文件方的:
public interface ICompositeOne {
@PostMapping("/One/uploadFile")
@ApiOperation(value = "上传文件---fegin的文件传递示例",notes = "上传文件---fegin的文件传递示例",tags = "OneAPI")
@ApiResponses(value = {@ApiResponse(code = 200,message = "成功"),
@ApiResponse(code = 500,message = "内部错误")})
boolean uploadFile(@RequestPart("multipartFile") MultipartFile multipartFile) throws Exception;
}
在composite加上pom文件的依赖
io.github.openfeign.form
feign-form
2.1.0
io.github.openfeign.form
feign-form-spring
2.1.0
方案一:参考自https://blog.csdn.net/tony_lu229/article/details/73823757
这篇文章写的很好,也比较全面,就是后面的排版比较乱,需要有耐心观看,现在对它的方法进行总结和改造
@FeignClient(name = "sum-one",configuration = FeignMultipartSupportConfig.class)
public interface OneServiceClient extends IOne {
}
@Configuration
public class FeignMultipartSupportConfig {
@Bean
@Primary
@Scope("prototype")
public Encoder multipartFormEncoder() {
return new SpringFormEncoder();
}
@Bean
public feign.Logger.Level multipartLoggerLevel() {
return feign.Logger.Level.FULL;
}
}
这种方案的话@Configuration会影响到所有的FeignClient ,因为是用的 spring的注解,直接注入到了容器中,会导致所有的FeignClient都会产生影响,不仅仅是这个问题,还有FeignMultipartSupportConfig 这个类中的代码会影响到其他的接口传递,SpringFormEncoder只对byte[]和String有用,如果其他的接口传递是一个对象就会报错,报错如下:
feign.codec.EncodeException: class com.aspire.sum.one.api.dto.Req is not a type supported by this encoder.
所以就有了方案二:
方案二的解决是解决了全局配置FeignClient的问题,我们可以在FeignMultipartSupportConfig这个类中不加@Configuration的注解,这样就不会去全局的配置FeignClient,可以在其他的FeignClient的接口进行参数的传递,但是这样会比较麻烦,因为会影响到同一个FeignClient的其他接口,相当于要专门为传递文件加入了FeignClient专有的,所以就有了方案三:
方案三:
从根本上解决了FeignMultipartSupportConfig中的方法会影响其他接口的传参问题,话不多说,直接上代码:
import feign.codec.Encoder;
import feign.form.spring.SpringFormEncoder;
import org.springframework.beans.factory.ObjectFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.web.HttpMessageConverters;
import org.springframework.cloud.netflix.feign.support.SpringEncoder;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Primary;
import org.springframework.context.annotation.Scope;
public class FeignMultipartSupportConfig {
////会影响其他的接口传递的参数,传对象会报错
// @Bean
// @Primary
// @Scope("prototype")
// public Encoder multipartFormEncoder() {
// return new SpringFormEncoder();
// }
//
// @Bean
// public feign.Logger.Level multipartLoggerLevel() {
// return feign.Logger.Level.FULL;
// }
//不会影响其他接口的传参,可以传对象、文件等
@Autowired
private ObjectFactory messageConverters;
@Bean
public Encoder feignFormEncoder() {
return new SpringFormEncoder(new SpringEncoder(messageConverters));
}
}
这个方法取消了@Configuration的注解的同时,又对同一个FeignClient的其他接口的传参不会影响
总结:方案:首先在pom文件中加入依赖,在文件接收方加入相关的注解,在文件发送方加入配置FeignClient的类,然后对相对应的FeignClient配置该类就好
关于参考的博客路径:https://blog.csdn.net/wangzhijie218/article/details/104638205?depth_1-utm_source=distribute.pc_relevant.none-task&utm_source=distribute.pc_relevant.none-task
https://blog.csdn.net/ytzzh0726/article/details/79467843