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进行文件上传+表单调用的更多相关文章

  1. 【Flask】 结合wtforms的文件上传表单

    表单中的文件上传 基本的表单渲染,表单类设置等等就不多说了,参看另一个文章即可.但是那篇文章里没有提到对于FileField,也就是上传文件的表单字段是如何处理,后端又是如何实现接受上传过来的文件的. ...

  2. 上传漏洞科普[1]-文件上传表单是Web安全主要威胁

    为了让最终用户将文件上传到您的网站,就像是给危及您的服务器的恶意用户打开了另一扇门.即便如此,在今天的现代互联网的Web应用程序,它是一种 常见的要求,因为它有助于提高您的业务效率.在Facebook ...

  3. 原生js封装ajax:传json,str,excel文件上传表单提交

    由于项目中需要在提交ajax前设置header信息,jquery的ajax实现不了,我们自己封装几个常用的ajax方法. jQuery的ajax普通封装 var ajaxFn = function(u ...

  4. Feign实现文件上传下载

    Feign框架对于文件上传消息体格式并没有做原生支持,需要集成模块feign-form来实现. 独立使用Feign 添加模块依赖: <!-- Feign框架核心 --> <depen ...

  5. flask 文件上传(单文件上传、多文件上传)

    文件上传 在HTML中,渲染一个文件上传字段只需要将<input>标签的type属性设为file,即<input type=”file”>. 这会在浏览器中渲染成一个文件上传字 ...

  6. ajax上传表单的俩种方式

    1.用h5对象上传表单(图片) var formData = new FormData(); formData.append("authenticity_token", '1212 ...

  7. bootstrap上传表单的时候上传的数据默认是0 一定要小心

    bootstrap上传表单的时候上传的数据默认是0 一定要小心

  8. spring boot:单文件上传/多文件上传/表单中多个文件域上传(spring boot 2.3.2)

    一,表单中有多个文件域时如何实现说明和文件的对应? 1,说明和文件对应 文件上传页面中,如果有多个文件域又有多个相对应的文件说明时, 文件和说明如何对应? 我们在表单中给对应的file变量和text变 ...

  9. 使用ajax上传表单(带文件)

    在使用form表单的时候上传文件+表单,会使得页面跳转,而在某些时候不希望跳转,只变化页面中的局部信息 通过查找资料,可以使用FormData进行ajax操作. FormData介绍:XMLHttpR ...

随机推荐

  1. 关于连接不上SVN的部分解决方案——No repository found in svn localhost

    今天如往常一样做事,期间发现一个问题,于是就打算将文件与 svn 上的文件进行对比,可谁成想 Eclipse 突然弹框报错,然后我到SVN资源库中直接刷新打开 svn 的地址,又弹框报错:文件夹不存在 ...

  2. struts2启动报错:ERROR com.opensymphony.xwork2.conversion.impl.DefaultConversionPropertiesProcessor - Conversion registration error

    [framework] 2019-12-05 11:34:05,441 - org.springframework.web.context.ContextLoader -5352 [RMI TCP C ...

  3. Docker 0x06: Docker Volume卷

    目录 Docker Volume卷 一句话什么是docker volume? docker volume特性 docker 挂载卷 docker 多容器间共享数据券 删除,查看数据卷 备份还原数据卷 ...

  4. linux cgroups简介(下)Cgroups 与 Systemd

    Cgroups 是 linux 内核提供的一种机制,如果你还不了解 cgroups,请参考前文<Linux cgroups 简介>先了解 cgroups.当 Linux 的 init 系统 ...

  5. python与设计模式--单例模式

    https://zhuanlan.zhihu.com/p/31675841 设计模式分类 创建类 单例模式.工厂模式.抽象工厂模式.原型模式.建造者模式 结构类 装饰器模式.适配器模式.门面模式.组合 ...

  6. 高小兰 201671010414 实验十四 团队项目评审&课程学习总结

    项目 内容 软件工程 https://www.cnblogs.com/nwnu-daizh/ 作业要求 https://www.cnblogs.com/sunmiaokun/p/11095027.ht ...

  7. php解析xml的几种方式

    php提供几种解析xml的类或方法,包括:Xml parser. SimpleXML,.XMLReader,.DOMDocument. XML Expat Parser: XML Parser使用Ex ...

  8. MVC 自己创建URL 对象处理路径

    var url = new UrlHelper(filterContext.RequestContext); var url = new UrlHelper(HttpContext.Current.R ...

  9. springboot 打包插件spring-boot-maven-plugin打包机制及内部结构分析

    今日思语:I miss you? 何解? 我错过你了?我想你了? 当下许多公司都会选择使用springboot作为服务应用开发框架,springboot框架提供了一套自己的打包机制,是通过spring ...

  10. 2017icpc beijing-I题-Colored Nodes

    题意 给定一个n个点m条边的无向图,一开始点i的颜色为i,在第i+kn秒开始时,与节点i相邻的节点会被染成i的颜色(k为自然数) 定义D(i,j)第j秒结束时颜色为i的节点个数,求: $F(i)=\l ...