1、引入POM
<!-- Feign -->
<dependency>
<groupId></groupId>
<artifactId>spring-cloud-starter-feign</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
<groupId></groupId>
<artifactId>feign-form</artifactId>
<version>3.3.0</version>
</dependency>
<dependency>
<groupId></groupId>
<artifactId>feign-form-spring</artifactId>
<version>3.3.0</version>
</dependency>
2、编写配置类
import ;
import ;
import ;
import ;
import ;
import ;
@Configuration
public class FeignMultipartSupportConfig {
@Bean
@Primary
@Scope("prototype")
public Encoder multipartFormEncoder() {
return new SpringFormEncoder();
}
@Bean
public multipartLoggerLevel() {
return ;
}
}
3、使用
import ;
import ;
import ;
import ;
import ;
import ;
//common是eureka中的一个服务提供者
@FeignClient(name="common", configuration=)
public interface FeignUploadService {
@RequestMapping(value="uploadImg", produces = {MediaType.APPLICATION_JSON_UTF8_VALUE},consumes = MediaType.MULTIPART_FORM_DATA_VALUE)
public OSSFile uploadImg(@RequestPart MultipartFile file);
}
就是,大功告成。
但是,如果你一不小心,可能就会遇到这样一个坑,使用Feign上传文件,MultipartFile文件死活传不过去。
前端调用接口,通过form表单向我提交这两个参数。参数名分别叫userId和headImg。
我的controller层接受到这两个参数后,向后传递,一直到feign。然而,我通过feign调用的其他服务的接口,图片的参数名叫file。我在feign里通过注解来指定图片文件的参数名,但是没用,死活传不过去。
public class UserController{
@Autowired
private Feign feign;
@PostMapping("/headImg")
public Result updateHeadImg(@RequestParam("userId") String userId, @RequestParam("headImg") MultipartFile headImg){
//前端给我传图片使用的参数名是headImg
return (userId, headImg);
}
}
我的feign代码大概如下
@FeignClient(name="app-user-service")
public interface Feign{
//前端给我传递的图片叫fileImage,而我调用的接口,图片参数名叫headImage,所以此处我在@RequestPart注解中,指定图片文件的参数名叫file
@PostMapping(value="/path", consumes = MediaType.MULTIPART_FORM_DATA_VALUE)
Result<Type> updateHeadImg(@RequestParam(value = "userId") String userId, @RequestPart(value="file") MultipartFile file);
}
我通过feign调用的远端接口代码大概如下:
public class AppUserController{
@Autowired
private UserService userService;
@PostMapping("/upHeadPortrait")
public Result upHeadPortrait(@RequestParam("userId") String userId, @NotNull MultipartFile file){
//这个别的微服务的接口,接收图片使用的参数名是file
return (userId, file);
}
}
我发现,无论我在feign中怎么指定参数名,图片文件到了远端接口,就是null,死活传不过去。
解决办法
把远端接口接收到的HttpServletRequest拿出来,看看到底我通过feign发起的request。
于是我在远端的接口里添加参数HttpServletRequest,把request里的parts拿出来看一眼。
请看代码:
public class AppUserController{
@Autowired
private UserService userService;
@PostMapping("/upHeadPortrait")
public Result upHeadPortrait(@RequestParam("userId") String userId, @NotNull MultipartFile file,
HttpServletRequest request){
//这个别的微服务的接口,接收图片使用的参数名是file
Collection<Part> parts = ();
((parts, true));
return (userId, file);
}
}
以下是logger打印出来的,parts的内容:
[
{
"contentType":"image/jpeg",
"headerNames":["content-disposition","content-type","content-transfer-encoding"],
"inputStream":{
"channel":{
"open":true
},
"fD":{}
},
"name":"headImg",
//图片的大小
"size":3734,
//这是我上传的图片文件的名字
"submittedFileName":""
}
]
并不是图片没有通过feign传递。而是传递过去后,name不是file,而是叫headImg。通过feign里的注解@RequestPart的value属性指定的参数名,并不生效。最终决定参数名的,就是前端传递到我的controller的图片参数的名字。