Feigin默认是不支持文件上传和表单提交的,需要做一些配置才能支持。

1、feign依赖

图中红色为form支持必须的jar。

2、添加自定义Encoder类:

  1. import java.lang.reflect.Type;
  2. import java.util.HashSet;
  3. import java.util.Map;
  4. import java.util.Set;
  5.  
  6. import org.springframework.web.multipart.MultipartFile;
  7.  
  8. import feign.RequestTemplate;
  9. import feign.codec.EncodeException;
  10. import feign.form.spring.SpringFormEncoder;
  11. import lombok.val;
  12. import sun.reflect.generics.reflectiveObjects.ParameterizedTypeImpl;
  13.  
  14. import static java.util.Collections.singletonMap;
  15.  
  16. /**
  17. * @author roger yang
  18. * @date 10/22/2019
  19. */
  20. public class MultipartEncoder extends SpringFormEncoder {
  21.  
  22. @SuppressWarnings("unchecked")
  23. @Override
  24. public void encode (Object object, Type bodyType, RequestTemplate template) throws EncodeException {
  25. if (bodyType.getClass().equals(ParameterizedTypeImpl.class) && ((ParameterizedTypeImpl) bodyType).getRawType().equals(Map.class)) {
  26. val data = (Map<String, Object>) object;
  27. Set<String> nullSet = new HashSet<>();
  28. for (Map.Entry<String, Object> entry : data.entrySet()) {
  29. if (entry.getValue() == null) {
  30. nullSet.add(entry.getKey());
  31. }
  32. }
  33. for (String s : nullSet) {
  34. data.remove(s);
  35. }
  36. super.encode(data, MAP_STRING_WILDCARD, template);
  37. return;
  38. } else if (bodyType.equals(MultipartFile.class)) {
  39. val file = (MultipartFile) object;
  40. val data = singletonMap(file.getName(), object);
  41. super.encode(data, MAP_STRING_WILDCARD, template);
  42. return;
  43. } else if (bodyType.equals(MultipartFile[].class)) {
  44. val file = (MultipartFile[]) object;
  45. if (file != null) {
  46. val data = singletonMap(file.length == 0 ? "" : file[0].getName(), object);
  47. super.encode(data, MAP_STRING_WILDCARD, template);
  48. return;
  49. }
  50. }
  51. super.encode(object, bodyType, template);
  52. }
  53. }

为什么要自定义呢?因为SpringFormEncoder这个类的源码里只对MultipartFile做了特殊处理,并未对MultipartFile[]数组进行处理,在传递多个文件时会报错。

  1. @Override
  2. public void encode (Object object, Type bodyType, RequestTemplate template) throws EncodeException {
  3. if (!bodyType.equals(MultipartFile.class)) {
  4. super.encode(object, bodyType, template);
  5. return;
  6. }
  7.  
  8. val file = (MultipartFile) object;
  9. val data = singletonMap(file.getName(), object);
  10. super.encode(data, MAP_STRING_WILDCARD, template);
  11. }

另外,我们为了让文件和表单一起在http的body里一起传输,所有我们将他们都封装到map里统一处理。

3、feign接口类:

  1. import java.util.Map;
  2.  
  3. import org.springframework.http.MediaType;
  4. import org.springframework.web.bind.annotation.RequestMapping;
  5. import org.springframework.web.bind.annotation.RequestMethod;
  6.  
  7. import com.longge.common.GlobalResponse;
  8.  
  9. /**
  10. * @author: yangzhilong
  11. * @description: Notification api
  12. * post with MULTIPART_FORM_DATA_VALUE
  13. * you client feign config:
  14. * -------------------------------------------------------------------
  15. * import org.springframework.cloud.openfeign.FeignClient;
  16. import org.springframework.context.annotation.Bean;
  17.  
  18. import com.longge.api.NotificationService;
  19.  
  20. import feign.codec.Encoder;
  21. import com.longge.config.MultipartEncoder;
  22.  
  23. @FeignClient(value = "notification-service", configuration = NotificationServiceFeign.FeignSimpleEncoderConfig.class)
  24. public interface NotificationServiceFeign extends NotificationMultipartService {
  25. class FeignSimpleEncoderConfig {
  26.  
  27. @Bean
  28. public Encoder encoder(){
  29. return new MultipartEncoder();
  30. }
  31. }
  32. }
  33. * ---------------------------------------------------------------------
  34. * @date: 17:24 2019/7/3
  35. **/
  36. @RequestMapping(value = "/v1/api")
  37. public interface NotificationMultipartService {
  38.  
  39. /**
  40. * common email channel ,use to send common email
  41. *
  42. * @param data
  43. * map key have:
  44. * attachfile --> MultipartFile[]
  45. * com.longge.dto.EmailDto.FieldName --- > value
  46. *
  47. * eg:
  48. * Map<String, Object> data = new HashMap<>();
  49. data.put("attachfile", new MultipartFile[] {file});
  50. data.put("from", emailDto.getFrom());
  51. data.put("to", emailDto.getTo());
  52. data.put("bodyText", emailDto.getBodyText());
  53. data.put("subject", emailDto.getSubject());
  54. * @return GlobalResponse<Long> email id
  55. */
  56. @RequestMapping(value = "/send_mail", method = RequestMethod.POST, produces = {MediaType.APPLICATION_JSON_UTF8_VALUE}, consumes = MediaType.MULTIPART_FORM_DATA_VALUE)
  57. GlobalResponse<String> sendMail(Map<String, Object> data);
  58. }

其中为了支持 form请求,需要对此feign进行单独的配置:

  1. import org.springframework.cloud.openfeign.FeignClient;
  2. import org.springframework.context.annotation.Bean;
  3.  
  4. import com.longge.api.NotificationMultipartService;
  5.  
  6. import feign.codec.Encoder;
  7.  
  8. @FeignClient(value = "notification-service", configuration = NotificationServiceFeign.FeignSimpleEncoderConfig.class)
  9. public interface NotificationServiceFeign extends NotificationMultipartService {
  10. class FeignSimpleEncoderConfig {
  11. @Bean
  12. public Encoder encoder() {
  13. return new MyEncoder();
  14. }
  15. }
  16. }

4、服务实现类

  1. @RequestMapping(value = "/v1/api/send_mail", method = RequestMethod.POST, consumes = MediaType.MULTIPART_FORM_DATA_VALUE, produces = {MediaType.APPLICATION_JSON_VALUE})
  2. public GlobalResponse<String> sendMail(@RequestParam(value = "attachfile", required = false) MultipartFile[] attachfile, EmailDto emailDto) {
  3. // TODO
  4. }

5、EmailDto属性

  1. private String from;
  2. private String to;
  3. private String subject;
  4. private String bodyText;
  5. 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. Redis系列-第六篇哨兵模式

    https://blog.csdn.net/niugang0920/article/details/97141175 Redis的主从复制模式下, 一旦主节点由于故障不能提供服务, 需要人工将从节点晋 ...

  2. springboot配置tomcat大全

    server.tomcat.accept-count=100 # Maximum queue length for incoming connection requests when all poss ...

  3. Mock Server之接口信息从DB获取

    上一篇,写了Mock Server的基础实现与被测系统的对接 当我们mock的接口信息.返回值等时不时维护时,都要在代码中编辑,那体验就不太好了,如果这些可以直接在浏览器编辑就好了. 因此对后端部分做 ...

  4. 逆向破解之160个CrackMe —— 021

    CrackMe —— 021 160 CrackMe 是比较适合新手学习逆向破解的CrackMe的一个集合一共160个待逆向破解的程序 CrackMe:它们都是一些公开给别人尝试破解的小程序,制作 c ...

  5. python3 networkx

    一.networkx 1.用于图论和复杂网络 2.官网:http://networkx.github.io/ 3.networkx常常结合numpy等数据处理相关的库一起使用,通过matplot来可视 ...

  6. httprunner学习5-参数化与数据驱动

    前言 参数化是自动化测试离不开的话题,httprunner里面只要把上一篇声明变量学会了,参数化也就自然会了. 不同的地方在于声明变量时对应值只有一个,参数化是多个值,存放在list里面. httpr ...

  7. Ubuntu只读文件系统修复方法

    首先备份重要数据 fsck.ext4 -p /dev/sdb5 reboot

  8. 最小球覆盖——模拟退火&&三分套三分套三分

    题目 给出 $N(1 \leq N \leq 100)$ 个点的坐标 $x_i,y_i,z_i$($-100000 \leq x_i,y_i,z_i \leq 100000$),求包围全部点的最小的球 ...

  9. Longest Common Substring SPOJ - LCS (后缀自动机)

    Longest Common Substring \[ Time Limit: 294ms \quad Memory Limit: 1572864 kB \] 题意 给出两个串,求两个串的最长公共连续 ...

  10. cc2530中单片机的通用I/O接口

    cc2530中有21个输入/输出引脚. 这些引脚可以设置为通用I/O或者设置为外设I/O.(其实这里的外设还是不太懂到底指什么,网上说输入设备,但是通用I/O也可以输入啊,为什么要弄外设I/O?) 其 ...