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. Java JDBC 操作二进制数据、日期时间

    二进制数据 mysql提供了四种类型来存储二进制数据: TinyBlob    最多可存储255字节 Blob   最多可存储65KB MediumBlob    最多可存储16MB LongBlob ...

  2. PHP实现Redis单据锁,防止并发重复写入

    一.写在前面 在整个供应链系统中,会有很多种单据(采购单.入库单.到货单.运单等等),在涉及写单据数据的接口时(增删改操作),即使前端做了相关限制,还是有可能因为网络或异常操作产生并发重复调用的情况, ...

  3. mysql 外键的基本使用

    外键的使用条件: 两个表必须是InnoDB表,MyISAM表暂时不支持外键外键列必须建立了索引,MySQL 4.1.2以后的版本在建立外键时会自动创建索引,但如果在较早的版本则需要显式建立:外键关系的 ...

  4. restframework详细

    1.写视图的方法 1.1第一种:原始APIView url(r'^login/$',account.LoginView.as_view()), from rest_framework.views im ...

  5. 网络空间安全基础篇(1)----nmap的使用

    nmap工具通俗一点说,就是利用nmap工具来对靶机的所有端口及其开启的服务进行扫描,以便于黑客入侵靶机时,知道用什么漏洞去攻击. nmap常用的命令集(标为红色的一般为常用参数): sV 扫描版本O ...

  6. 软工团队第三次作业——编码组Alpha版本

    众志陈成组 柚荐--Alpha版本 编码部分 一.编码思路 思维导图如下 二.下载及操作方法 1.下载地址 GitHub地址:https://github.com/NyimaC/YouSuggest ...

  7. try catch 小结 , node的回调callback里不能捕获异常 , 不能被v8优化(现在能了),

    <深入浅出Nodejs>时,在第四章 - 异步编程中作者朴灵曾提到,异步编程的难点之一是异常处理,书中描述"尝试对异步方法进行try/catch操作只能捕获当次事件循环内的异常, ...

  8. 常用 shell 命令 chmod | root

    chmod 命令 chmod 命令 [格式1:] chmod [ugoa][+-=][rwx] 文件或目录 /*u.g.o.a : u属主,g属组,o其他用户,a所有用户*/ /*+.-.= : 增加 ...

  9. SpringBoot 之Spring Boot Starter依赖包及作用(自己还没有看)

    spring-boot-starter 这是Spring Boot的核心启动器,包含了自动配置.日志和YAML. spring-boot-starter-amqp 通过spring-rabbit来支持 ...

  10. 在调试时,有什么更好的方法可以监视最后一个win32错误?

    我发现在代码中使用win32api时,需要多次监视最后一个win32错误!(在每次使用API后调用GetLastError()是不可行的解决方案!).. 在Visual Studio中,它们提供了一个 ...