Spring Cloud Feign 上传文件的常见问题

Feign 作为 Spring Cloud 中 RPC 工具,利用注解来描述接口,简化了 Java HTTP Client 的调用过程,隐藏了实现细节。

本文将介绍利用 Feign 上传文件的几个常见问题。

  • 如何上传一个/组文件

  • 如何上传多种文件

  • MultipartFile 参数不能为空问题

  • 未提供 MultipartFile 参数接口报 no multipart boundary was found 问题

如何上传一个/组文件

OpenFeign 默认不支持文件参数,但提供了 feign-form 拓展工具,这里简单拓展下官方Demo。

引入 io.github.openfeign.form: feign-form:3.8.0 io.github.openfeign.form: feign-form-spring:3.8.0 maven依赖,注入 SpringFormEncoder ,在 @FeignClient 中配下configuration即可。


@FeignClient(value = "cms-service", configuration = CmsService.MyConfig.class)

public interface CmsService {

// 也可以使用MultipartFile[]上传多个文件

@PostMapping(value = "upload", consumes = MediaType.MULTIPART_FORM_DATA_VALUE)

void upload(@RequestPart("file") MultipartFile file);


class MyConfig {

@Bean

public Encoder feignFormEncoder() {

return new SpringFormEncoder();

}

}

}

如果需要使用Spring标准的encoder,config变一下。


class MyConfig {

@Autowired

private ObjectFactory<HttpMessageConverters> messageConverters;


@Bean

public Encoder feignFormEncoder () {

return new SpringFormEncoder(new SpringEncoder(messageConverters));

}

}

需要特别注意 feign-form OpenFeign  版本之间的关系,官方描述如下:

Spring Cloud Feign 上传文件的常见问题

如何上传多种文件

如下,假设有file1、file2两个文件,且不是数组。


@FeignClient(value = "cms-service")

public interface CmsService {

@PostMapping(value = "upload", consumes = MediaType.MULTIPART_FORM_DATA_VALUE)

void upload(@RequestPart("file1") MultipartFile file1,

(@RequestPart("file2") MultipartFile file2);

}

在应用启动时处理CmsService时,就会直接报错:


IllegalStateException:

Method has too many Body parameters

Feign 不支持多个body参数。本身一次上传多个文件场景少见,改为每次传一个就好。

MultipartFile 参数不能为空

假设有MultipartFile类型参数,但 required 设置为 false


@FeignClient(value = "cms-service")

public interface CmsService {

@PostMapping(value = "upload", consumes = MediaType.MULTIPART_FORM_DATA_VALUE)

void upload(@RequestPart(value = "file", required = false) MultipartFile file);

}

会报错:


Caused by: java.lang.IllegalArgumentException:

Body parameter 6 was null

这个问题 Body parameter was null problem when MultipartFile param is null  最近我在Github问过,解释是 Feign不支持这种特性,如果有需要,可以通过设置多个API解决,例子如下:


public interface MailClient {

@PostMapping("/send", consumes = MediaType.APPLICATION_FORM_URL_ENCODED)

void send(@RequestParam("message") String message);


@PostMapping("/send", consumes = MediaType.MULTIPART_FORM_DATA_VALUE)

void send(@RequestParam("message") String message,

@RequestPart("attachment") MultipartFile file);

}

no multipart boundary was found 问题

上次一步的例子会引发新的问题,假设一个接口提供了两个参数。


@RestController

public class FileController {

@PostMapping("/upload", consumes = MediaType.MULTIPART_FORM_DATA_VALUE)

void upload(@RequestParam("message") String message,

@RequestPart("attachment") MultipartFile file);

}

但使用时未提供MultipartFile类型参数。


@FeignClient(value = "cms-service")

public interface CmsService {

@PostMapping(value = "upload", consumes = MediaType.MULTIPART_FORM_DATA_VALUE)

void upload(@RequestParam("message") String message, );

}

将会报如下错误:


org.apache.tomcat.util.http.fileupload.FileUploadException:

the request was rejected because no multipart boundary was found

这是因为Feign只有存在MultipartFile类型参数时才会设置 boundary 。在Feign的 MultipartFormContentProcessor 中,其中有一点就专门是用来添加boundary。


public void process(…) throws EncodeException {

String boundary = Long.toHexString(System.currentTimeMillis());

output.write("–").write(boundary).write("–").write("/r/n");

String contentTypeHeaderValue = this.getSupportedContentType().getHeader() + "; charset=" + charset.name() + "; boundary=" + boundary;

template.header("Content-Type", new String[]{contentTypeHeaderValue});

}

如果自己处理的话,可以在 RequestInterceptor 的实现类中模拟上面的方法,为 multipart/form-data 格式自定义一个boundary。

小结

本文是一遍工具使用帖,小结一下,传文件注意几个点:

  • Feign 不支持多个body参数,body参数也不能为空

  • 特别注意 feign-form 的版本

若对Feign源码感兴趣,可看看 Spring Cloud 源码学习之 Feign 。

喜欢可关注公众号[陈一乐]

原文 

https://mp.weixin.qq.com/s/MU8X4YjF724xa1UwsWM_Kg

本站部分文章源于互联网,本着传播知识、有益学习和研究的目的进行的转载,为网友免费提供。如有著作权人或出版方提出异议,本站将立即删除。如果您对文章转载有任何疑问请告之我们,以便我们及时纠正。

PS:推荐一个微信公众号: askHarries 或者qq群:474807195,里面会分享一些资深架构师录制的视频录像:有Spring,MyBatis,Netty源码分析,高并发、高性能、分布式、微服务架构的原理,JVM性能优化这些成为架构师必备的知识体系。还能领取免费的学习资源,目前受益良多

转载请注明原文出处:Harries Blog™ » Spring Cloud Feign 上传文件的常见问题

赞 (0)
分享到:更多 ()

评论 1

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址
  1. 等你困惑了我一周的问题,终于找到问题根源了。原来是版本对不上,感谢博主的分享回复