昨天同事發給我一個異常的截圖,說是用@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