Feign进行文件上传+表单调用
Feigin默认是不支持文件上传和表单提交的,需要做一些配置才能支持。
1、feign依赖

图中红色为form支持必须的jar。
2、添加自定义Encoder类:
import java.lang.reflect.Type;
import java.util.HashSet;
import java.util.Map;
import java.util.Set; import org.springframework.web.multipart.MultipartFile; import feign.RequestTemplate;
import feign.codec.EncodeException;
import feign.form.spring.SpringFormEncoder;
import lombok.val;
import sun.reflect.generics.reflectiveObjects.ParameterizedTypeImpl; import static java.util.Collections.singletonMap; /**
* @author roger yang
* @date 10/22/2019
*/
public class MultipartEncoder extends SpringFormEncoder { @SuppressWarnings("unchecked")
@Override
public void encode (Object object, Type bodyType, RequestTemplate template) throws EncodeException {
if (bodyType.getClass().equals(ParameterizedTypeImpl.class) && ((ParameterizedTypeImpl) bodyType).getRawType().equals(Map.class)) {
val data = (Map<String, Object>) object;
Set<String> nullSet = new HashSet<>();
for (Map.Entry<String, Object> entry : data.entrySet()) {
if (entry.getValue() == null) {
nullSet.add(entry.getKey());
}
}
for (String s : nullSet) {
data.remove(s);
}
super.encode(data, MAP_STRING_WILDCARD, template);
return;
} else if (bodyType.equals(MultipartFile.class)) {
val file = (MultipartFile) object;
val data = singletonMap(file.getName(), object);
super.encode(data, MAP_STRING_WILDCARD, template);
return;
} else if (bodyType.equals(MultipartFile[].class)) {
val file = (MultipartFile[]) object;
if (file != null) {
val data = singletonMap(file.length == 0 ? "" : file[0].getName(), object);
super.encode(data, MAP_STRING_WILDCARD, template);
return;
}
}
super.encode(object, bodyType, template);
}
}
为什么要自定义呢?因为SpringFormEncoder这个类的源码里只对MultipartFile做了特殊处理,并未对MultipartFile[]数组进行处理,在传递多个文件时会报错。
@Override
public void encode (Object object, Type bodyType, RequestTemplate template) throws EncodeException {
if (!bodyType.equals(MultipartFile.class)) {
super.encode(object, bodyType, template);
return;
} val file = (MultipartFile) object;
val data = singletonMap(file.getName(), object);
super.encode(data, MAP_STRING_WILDCARD, template);
}
另外,我们为了让文件和表单一起在http的body里一起传输,所有我们将他们都封装到map里统一处理。
3、feign接口类:
import java.util.Map; import org.springframework.http.MediaType;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod; import com.longge.common.GlobalResponse; /**
* @author: yangzhilong
* @description: Notification api
* post with MULTIPART_FORM_DATA_VALUE
* you client feign config:
* -------------------------------------------------------------------
* import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.context.annotation.Bean; import com.longge.api.NotificationService; import feign.codec.Encoder;
import com.longge.config.MultipartEncoder; @FeignClient(value = "notification-service", configuration = NotificationServiceFeign.FeignSimpleEncoderConfig.class)
public interface NotificationServiceFeign extends NotificationMultipartService {
class FeignSimpleEncoderConfig { @Bean
public Encoder encoder(){
return new MultipartEncoder();
}
}
}
* ---------------------------------------------------------------------
* @date: 17:24 2019/7/3
**/
@RequestMapping(value = "/v1/api")
public interface NotificationMultipartService { /**
* common email channel ,use to send common email
*
* @param data
* map key have:
* attachfile --> MultipartFile[]
* com.longge.dto.EmailDto.FieldName --- > value
*
* eg:
* Map<String, Object> data = new HashMap<>();
data.put("attachfile", new MultipartFile[] {file});
data.put("from", emailDto.getFrom());
data.put("to", emailDto.getTo());
data.put("bodyText", emailDto.getBodyText());
data.put("subject", emailDto.getSubject());
* @return GlobalResponse<Long> email id
*/
@RequestMapping(value = "/send_mail", method = RequestMethod.POST, produces = {MediaType.APPLICATION_JSON_UTF8_VALUE}, consumes = MediaType.MULTIPART_FORM_DATA_VALUE)
GlobalResponse<String> sendMail(Map<String, Object> data);
}
其中为了支持 form请求,需要对此feign进行单独的配置:
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.context.annotation.Bean; import com.longge.api.NotificationMultipartService; import feign.codec.Encoder; @FeignClient(value = "notification-service", configuration = NotificationServiceFeign.FeignSimpleEncoderConfig.class)
public interface NotificationServiceFeign extends NotificationMultipartService {
class FeignSimpleEncoderConfig {
@Bean
public Encoder encoder() {
return new MyEncoder();
}
}
}
4、服务实现类
@RequestMapping(value = "/v1/api/send_mail", method = RequestMethod.POST, consumes = MediaType.MULTIPART_FORM_DATA_VALUE, produces = {MediaType.APPLICATION_JSON_VALUE})
public GlobalResponse<String> sendMail(@RequestParam(value = "attachfile", required = false) MultipartFile[] attachfile, EmailDto emailDto) {
// TODO
}
5、EmailDto属性
private String from;
private String to;
private String subject;
private String bodyText;
private String bodyHtml;
感谢:https://blog.csdn.net/ytzzh0726/article/details/79731343
Feign进行文件上传+表单调用的更多相关文章
- 【Flask】 结合wtforms的文件上传表单
表单中的文件上传 基本的表单渲染,表单类设置等等就不多说了,参看另一个文章即可.但是那篇文章里没有提到对于FileField,也就是上传文件的表单字段是如何处理,后端又是如何实现接受上传过来的文件的. ...
- 上传漏洞科普[1]-文件上传表单是Web安全主要威胁
为了让最终用户将文件上传到您的网站,就像是给危及您的服务器的恶意用户打开了另一扇门.即便如此,在今天的现代互联网的Web应用程序,它是一种 常见的要求,因为它有助于提高您的业务效率.在Facebook ...
- 原生js封装ajax:传json,str,excel文件上传表单提交
由于项目中需要在提交ajax前设置header信息,jquery的ajax实现不了,我们自己封装几个常用的ajax方法. jQuery的ajax普通封装 var ajaxFn = function(u ...
- Feign实现文件上传下载
Feign框架对于文件上传消息体格式并没有做原生支持,需要集成模块feign-form来实现. 独立使用Feign 添加模块依赖: <!-- Feign框架核心 --> <depen ...
- flask 文件上传(单文件上传、多文件上传)
文件上传 在HTML中,渲染一个文件上传字段只需要将<input>标签的type属性设为file,即<input type=”file”>. 这会在浏览器中渲染成一个文件上传字 ...
- ajax上传表单的俩种方式
1.用h5对象上传表单(图片) var formData = new FormData(); formData.append("authenticity_token", '1212 ...
- bootstrap上传表单的时候上传的数据默认是0 一定要小心
bootstrap上传表单的时候上传的数据默认是0 一定要小心
- spring boot:单文件上传/多文件上传/表单中多个文件域上传(spring boot 2.3.2)
一,表单中有多个文件域时如何实现说明和文件的对应? 1,说明和文件对应 文件上传页面中,如果有多个文件域又有多个相对应的文件说明时, 文件和说明如何对应? 我们在表单中给对应的file变量和text变 ...
- 使用ajax上传表单(带文件)
在使用form表单的时候上传文件+表单,会使得页面跳转,而在某些时候不希望跳转,只变化页面中的局部信息 通过查找资料,可以使用FormData进行ajax操作. FormData介绍:XMLHttpR ...
随机推荐
- Kubernetes学习之原理
Kubernetes基本概念 一.Label selector在kubernetes中的应用场景 1.kube-controller-manager的replicaSet通过定义的label 来筛选要 ...
- python生成图片二维码(利用pillow)
首先 pip install pillow 然后 from PIL import Image from PIL import ImageDraw from PIL import ImageFont i ...
- Kubernetes学习之路(27)之k8s 1.15.2 部署
目录 一.环境准备 二.软件安装 三.部署master节点 四.部署node节点 五.集群状态检测 一.环境准备 IP地址 节点角色 CPU Memory Hostname Docker versio ...
- Gzip模块
Gzip模块为python的压缩和解压缩模块,读写gzip 文件 一.使用gzip模块压缩文件: 1 import gzip #导入python gzip模块,注意名字为全小写 2 g = gzip. ...
- linux设备驱动程序-i2c(2)-adapter和设备树的解析
linux设备驱动程序-i2c(2)-adapter和设备树的解析 (注: 基于beagle bone green开发板,linux4.14内核版本) 在本系列linux内核i2c框架的前两篇,分别讲 ...
- 启动keepalived报错(VI_1): received an invalid passwd!
一.署keepalived后测试主down掉后无法自动切换到备 查看message日志一直报此错误 [root@lb-nginx-master ~]# tailf /var/log/messages ...
- Kotlin匿名函数与闭包详解
Lambda表达式实例演练: 继续先来编写一些Lambda表达式相关的代码: 接下来想从上面的字符串数组中找到带有"h"的字符串并打印出来: 如果学习了Java8的Lambda表达 ...
- 如何获取gitee上的项目?
对于没有使用过github/gitee的朋友来说,估计是有点懵. 下面举个例子,比如获取我的gitee上的python接口自动化测试框架 访问主页:https://gitee.com/uncleyon ...
- Redux的图文模型
Also these are really nice (from http://slides.com/jenyaterpil/redux-from-twitter-hype-to-production ...
- 严重: Exception sending context initialized event to listener instance of class org.springframework.web.context.ContextLoaderListener
十月 30, 2019 11:12:35 下午 org.apache.catalina.core.StandardContext listenerStart 严重: Exception sending ...