昨天同事发给我一个异常的截图,说是用@FeignClient
上传文件时报错,我看了下方法的入参是MultipartFile
,于是采坑开始(此处省略一万字,一万匹***奔涌而过,某度真LJ),参考网上技术文章,是因为feign
不支持multipart/form
类型,需要引入feign-form、feign-form-spring
,于是在项目(spring-cloud:Greenwich.RELEASE
)中引入feign-form:3.3.0
和feign-form-spring:3.3.0
版本,但是不行啊,你文章里面说代码没问题,我这里就是不行,解决不了我自己的问题,还是需要自己来解决,没办法,看官方的介绍呗。
Requirements
The feign-form
extension depend on OpenFeign
and its concrete versions:
- all
feign-form
releases before 3.5.0 works withOpenFeign
9.* versions; - starting from
feign-form
's version 3.5.0, the module works withOpenFeign
10.1.0 versions and greater.
IMPORTANT: there is no backward compatibility and no any gurantee that the
feign-form
's versions after 3.5.0work withOpenFeign
before 10.*.OpenFeign
was refactored in 10th release, so the best approach - use the freshestOpenFeign
andfeign-form
versions.
Notes:
- spring-cloud-openfeign uses
OpenFeign
9.* till v2.0.3.RELEASE and uses 10.* after. Anyway, the dependency already has suitablefeign-form
version, see dependency pom, so you don't need to specify it separately; spring-cloud-starter-feign
is a deprecated dependency and it always uses theOpenFeign
's 9.* versions.
以上翻译过来大致意思如下:
feign-form
扩展依赖于open-feign
的特定版本
open-feign 9.*
版本对应使用feign-from 3.5.0
之前的版本
open-feign 10.1.0
以及以后的版本对应使用3.5.0
以及以后版本
feign-from 3.5.0
之后的版本没有兼容open-feign 10.*
之前的版本,10版本
的open-feign
重构了代码,所以最好的方法是用最新的版本
spring-cloud-openfeign:2.0.3.release
之前用open-feign 9.*
版本 ,2.0.3.release
之后的版本用open-feign 10.*
,且在2.0.3.release
之后的版本里面已经包含feign-form
的依赖,不需要再去指定相应的版本
spring-cloud-starter-feign
已经不推荐使用,他一来的依然是open-feign 9.*
好了看完github
上的介绍,又看了下项目的springcloud
版本Greenwich.RELEASE
,完全不需要任何其他的依赖了,已将包含了。
接下来简单介绍配合spring-cloud
正确的使用方法。
一、添加依赖
1.1、使用最新版本
<dependency>
<groupId>io.github.openfeign.form</groupId>
<artifactId>feign-form</artifactId>
<version>3.8.0</version>
</dependency>
<!--配合spring使用-->
<dependency>
<groupId>io.github.openfeign.form</groupId>
<artifactId>feign-form-spring</artifactId>
<version>3.8.0</version>
</dependency>
1.2、使用spring-cloud-starter-open-feign
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>
二选一,如果想使用最新3.8.0
版本,就使用1.1
二、服务提供者
MultipartFile
入参要用@RequestPart
注解修饰,而不是@RequestParam
,消费类型需指定为MediaType.MULTIPART_FORM_DATA_VALUE
/**
* 文件上传控制器
* @author DUCHONG
* @since 2020-09-16 16:10
**/
@RestController
@Slf4j
public class FileUploadController {
/***
* 上传文件
* @param file
* @return
*/
@RequestMapping(value = "/fileUpload",consumes = MediaType.MULTIPART_FORM_DATA_VALUE)
public String fileUpload(@RequestPart("file") MultipartFile file, @RequestParam("name") String name ) {
// 判断文件是否为空
if (!file.isEmpty()) {
try {
// 文件保存路径
String filePath = System.getProperty("user.dir")+ "/upload/"
+ file.getOriginalFilename();
// 转存文件
file.transferTo(new File(filePath));
} catch (Exception e) {
e.printStackTrace();
}
}
log.info("文件上传成功---fileName---{}",file.getOriginalFilename());
return file.getOriginalFilename();
}
}
三、Feign接口
@FeignClient
指定configuration
参数
@Configuration
public class MultipartSupportConfig {
@Autowired
private ObjectFactory<HttpMessageConverters> messageConverters;
@Bean
@Primary
@Scope("prototype")
public Encoder feignEncoder() {
return new SpringFormEncoder(new SpringEncoder(messageConverters));
}
}
MultipartFile
入参要用@RequestPart
注解修饰,而不是@RequestParam
consumes
消费类型需指定为MediaType.MULTIPART_FORM_DATA_VALUE
@FeignClient(value = "rest-provider",configuration = MultipartSupportConfig.class)
public interface FeignService {
/**
* 测试文件上传
* @param file
* @param name
* @return
*/
@RequestMapping(value = "/fileUpload",consumes = MediaType.MULTIPART_FORM_DATA_VALUE)
String uploadFile(@RequestPart("file") MultipartFile file, @RequestParam("name") String name);
四、服务消费者
/**
* @author DUCHONG
* @since 2019-03-25 16:25
**/
@RestController
@Slf4j
public class FeignController {
@Autowired
private FeignService feignService;
@RequestMapping(value = "/fileUpload")
public String fileUpload(@RequestPart("file") MultipartFile file, @RequestParam("name") String name ) {
log.info("文件上传---fileName---{}",file.getOriginalFilename());
return feignService.uploadFile(file,name);
}
}
五、Postman来一发
搞定!!!
完整代码已上传至github