使用Spring Cloud Feign上传文件的示例
最近经常有人问spring cloud feign如何上传文件。有团队的新成员,也有其他公司的兄弟。本文简单做个总结——
早期的spring cloud中,feign本身是没有上传文件的能力的(1年之前),要想实现这一点,需要自己去编写encoder 去实现上传。现在我们幸福了很多。因为feign官方提供了子项目feign-form ,其中实现了上传所需的 encoder 。
注:笔者测试的版本是edgware.release。camden、dalston同样适应本文所述。
加依赖
<dependency> <groupid>io.github.openfeign.form</groupid> <artifactid>feign-form</artifactid> <version>3.0.3</version> </dependency> <dependency> <groupid>io.github.openfeign.form</groupid> <artifactid>feign-form-spring</artifactid> <version>3.0.3</version> </dependency>
编写feign client
@feignclient(name = "ms-content-sample", configuration = uploadfeignclient.multipartsupportconfig.class) public interface uploadfeignclient { @requestmapping(value = "/upload", method = requestmethod.post, produces = {mediatype.application_json_utf8_value}, consumes = mediatype.multipart_form_data_value) @responsebody string handlefileupload(@requestpart(value = "file") multipartfile file); class multipartsupportconfig { @bean public encoder feignformencoder() { return new springformencoder(); } } }
如代码所示,在这个feign client中,我们引用了配置类multipartsupportconfig ,在multipartsupportconfig 中,我们实例化了springformencoder 。这样这个feign client就能够上传啦。
注意点
@requestmapping(value = "/upload", method = requestmethod.post, produces = {mediatype.application_json_utf8_value}, consumes = mediatype.multipart_form_data_value) 中的produeces 、consumes 不能少;
接口定义中的注解@requestpart(value = "file") 不能写成@requestparam(value = "file" 。
最好将hystrix的超时时间设长一点,例如5秒,否则可能文件还没上传完,hystrix就超时了,从而导致客户端侧的报错。
springcloud中使用feign的坑
示例如下:
@feignclient("service-resource") //@requestmapping("/api/test") public interface testresourceitg { @requestmapping(value = "/api/test/raw", method = requestmethod.post, consumes = "application/x-www-form-urlencoded") public string raw1(@pathvariable("subject") string subject, // 标题 @requestparam("content") string content); // 内容 }
说明:
*使用requestmapping中的consumes指定生成的请求的content-type
*requestparam指定的参数会拼接在url之后,如: ?name=xxx&age=18
*pathvariable指定的参数会放到一个linkedhashmap<string, ?>传入到feign的encoder中进行处理,而在spring中实现了该接口的encoder为springencoder,而该实现又会使用spring中的httpmessageconverter进行请求体的写入。
坑:
*不要在接口类名上使用requestmapping,虽然可以使用,但同时springmvc会把该接口的实例当作controller开放出去,这个可以在启动的mapping日志中查看到
*使用默认的springencoder,在不指定consumes时,pathvariable中的参数会生成json字符串发送,且默认情况下不支持form表单的生成方式,原因为:formhttpmessageconverter只能处理multivaluemap,而使用pathvariable参数被放在了hashmap中。默认更不支持文件上传。其实已经有支持处理各种情况的httpmessageconverter存在。
填坑:
*支持form表单提交:只需要编写一个支持map的formhttpmessageconverter即可,内部可调用formhttpmessageconverter的方法简化操作。
*支持文件上传:只需要把要上传的文件封装成一个resource(该resource一定要实现filename接口,这个是把请求参数解析成文件的标识),使用默认的resourcehttpmessageconverter处理即可。
*支持处理multipartfile参数:编写一个支持multipartfile的multipartfilehttpmessageconverter即可,内部可调用resourcehttpmessageconverter实现,同时注意需要将其添加至formhttpmessageconverter的parts中,并重写formhttpmessageconverter的getfilename方法支持从multipartfile中获取filename
*所有的httpmessageconverter直接以@bean的方式生成即可,spring会自动识别添加
完美支持表单和文件上传:
方案一:
使用附件中的mapformhttpmessageconverter.java和multipartfilehttpmessageconverter.java
在spring中进行如下配置即可
@bean public mapformhttpmessageconverter mapformhttpmessageconverter(multipartfilehttpmessageconverter multipartfilehttpmessageconverter) { mapformhttpmessageconverter mapformhttpmessageconverter = new mapformhttpmessageconverter(); mapformhttpmessageconverter.addpartconverter(multipartfilehttpmessageconverter); return mapformhttpmessageconverter; } @bean public multipartfilehttpmessageconverter multipartfilehttpmessageconverter() { return new multipartfilehttpmessageconverter(); }
方案二:
使用feignspringformencoder.java
在spring中配置如下:
@bean public encoder feignencoder(objectfactory<httpmessageconverters> messageconverters) { return new feignspringformencoder(messageconverters); }
推荐使用方案一
方案二为参考而来,未测
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持。
推荐阅读
-
使用Spring Cloud Feign上传文件的示例
-
详解spring cloud Feign使用中遇到的问题总结
-
使用Spring Cloud Feign作为HTTP客户端调用远程HTTP服务的方法(推荐)
-
Java实现拖拽文件上传dropzone.js的简单使用示例代码
-
Spring Boot 与 Kotlin 上传文件的示例代码
-
详解spring cloud Feign使用中遇到的问题总结
-
使用Spring Cloud Feign作为HTTP客户端调用远程HTTP服务的方法(推荐)
-
Spring Cloud如何使用Feign构造多参数的请求
-
Spring Cloud使用Feign实现Form表单提交的示例
-
Java实现拖拽文件上传dropzone.js的简单使用示例代码