SPRING+OPENFEIGN上传文件报错
OPENFEIGN 版本
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-openfeign</artifactId>
<version>2.2.2.RELEASE</version>
</dependency>
情况一
@FeignClient(url = "http://localhost:8080",configuration = MyConfig.class)
public interface SpringFeignTestInterface {
@RequestMapping(value = "/upload/{folder}", method = POST)
public ResponseEntity<UploadInfo> upload(@PathVariable("folder") String folder, @RequestParam("file") MultipartFile file, @RequestParam("metadata") UploadMetadata metadata) ;
}
直接使用 @RequestParam 标注上传文件,不能够正确运行
情况二
@ApiModel("文件上传请求")
public class FileUploadRequest {
@ApiModelProperty(value = "上传的文件", required = true)
private MultipartFile file;
private String operator;
}
@FeignClient(url = "http://localhost:8080",configuration = MyConfig.class)
public interface SpringFeignTestInterface {
@RequestMapping(value = "/upload/{folder}", method = POST)
public ResponseEntity<UploadInfo> upload(@RequestPart("request") FileUploadRequest request) ;
}
即使是将文件封存在 object 对象中,使用 @RequestPart 标注,也不能运行。这样的结果是只把文件传过去了,与其在一个类中的操作员,并不会随着一起传到文件管理系统。
情况三
@FeignClient(url = "http://localhost:8080",configuration = MyConfig.class)
public interface SpringFeignTestInterface {
@RequestMapping(value = "/upload/{folder}", method = POST)
public ResponseEntity<UploadInfo> upload(@RequestPart("folder") String folder, @RequestPart("file") MultipartFile file, @RequestPart("metadata") UploadMetadata metadata) ;
}
fegin 客户端接口使用多个 @RequestPart 标注所有的参数,项目在正确启动、使用过程中,不会出现错误,所有参数也能够正确传输,但是在跑 @Test 单元测试过程中,即使没有调用 FeignClient 中的方法,只是将其注入在 @Service 标注的类中,也会出现错误。具体错误信息如下。
Caused by: java.lang.IllegalStateException: Method has too many Body parameters: public abstract org.springframework.http.ResponseEntity au.com.macquarie.bfs.ml.store.v1.StoreClient.createFile(org.springframework.web.multipart.MultipartFile,java.util.Map)
情况四
@FeignClient(url = "http://localhost:8080",configuration = MyConfig.class)
public interface SpringFeignTestInterface {
@RequestMapping(value = "/upload/{folder}", method = POST)
public ResponseEntity<UploadInfo> upload(@PathVariable("folder") String folder, @PathVariable("file") MultipartFile file, @PathVariable("metadata") UploadMetadata metadata) ;
}
标注 @PathVariable ,当被该注解标注的时候,实际 URL 中没有相应的参数,则会被解析为 formParams 参数
情况五
@FeignClient(url = "http://localhost:8080",configuration = MyConfig.class)
public interface SpringFeignTestInterface {
@RequestMapping(value = "/upload/{folder}", method = POST)
public ResponseEntity<UploadInfo> upload(@RequestParam("folder") String folder, @RequestPart("file") MultipartFile file, @RequestParam("metadata") UploadMetadata metadata) ;
}
仅在要上传的文件标注 @RequestPart ,其他参数 标注 @RequestParam ,这是目前发现的最合适的办法。
GITHUB 上的示例
注意:
上述的操作都实现了自己 Feign 编码器。使用 feign 默认解析器(JacksonEncoder) 上述好多情况不一定能够复现。
@Configuration
public class MyConfig {
@Autowired
private ObjectFactory<HttpMessageConverters> messageConverters;
@Scope("prototype")
@Primary
@Bean
public Encoder feignFormecoder() {
return new SpringFormEncoder(new SpringEncoder(messageConverters));
}
}