Feign 接口多文件传递
1. Feign 接口中引入config
@FeignClient(value = "", contextId = "", path = "",configuration = {FeignFormConfig.class})
2. 引入pom
<dependency>
<groupId>io.github.openfeign.form</groupId>
<artifactId>feign-form</artifactId>
<version>3.8.0</version>
</dependency>
<dependency>
<groupId>io.github.openfeign.form</groupId>
<artifactId>feign-form-spring</artifactId>
<version>3.8.0</version>
</dependency>
3. 写 config
public class FeignFormConfig {
/**
* Multipart File编码支持
*
* @param messageConvertersObjectFactory 容器中已有的转化器集合
* @return Multipart File编码器
*/
@Bean
public Encoder springFormEncoder(ObjectFactory<HttpMessageConverters> messageConvertersObjectFactory) {
// 避免实体作为参数无法接收
SpringEncoder springEncoder = new SpringEncoder(messageConvertersObjectFactory);
return new SpringMultipartEncoder(springEncoder);
}
}
public class SpringMultipartEncoder extends FormEncoder {
/**
* Constructor with the default Feign's encoder as a delegate.
*/
public SpringMultipartEncoder() {
this(new Default());
}
/**
* Constructor with specified delegate encoder.
*
* @param delegate delegate encoder, if this encoder couldn't encode object.
*/
public SpringMultipartEncoder(Encoder delegate) {
super(delegate);
val processor = (MultipartFormContentProcessor) getContentProcessor(MULTIPART);
processor.addFirstWriter(new SpringSingleMultipartFileWriter());
processor.addFirstWriter(new SpringManyMultipartFilesWriter());
}
/**
* 文件编码,需要注意file/files两个参数需要与服务端参数保持一致
*
* @param object 文件对象
* @param bodyType 文件类型
* @param template request
* @throws EncodeException 编码异常
*/
@Override
public void encode (Object object, Type bodyType, RequestTemplate template) throws EncodeException {
if (bodyType.equals(MultipartFile[].class)) {
// 此处为改造之处,SpringFormEncoder中将多个文件合成了一个文件,此处添加多个文件
val files = (MultipartFile[]) object;
Map<String, MultipartFile[]> data = Collections.singletonMap("files", files);
super.encode(data, MAP_STRING_WILDCARD, template);
} else if (bodyType.equals(MultipartFile.class)) {
val data = singletonMap("file", object);
super.encode(data, MAP_STRING_WILDCARD, template);
} else if (isMultipartFileCollection(object)) {
val iterable = (Iterable<?>) object;
val data = new HashMap<String, Object>();
for (val item : iterable) {
val file = (MultipartFile) item;
data.put(file.getName(), file);
}
super.encode(data, MAP_STRING_WILDCARD, template);
} else {
super.encode(object, bodyType, template);
}
}
private boolean isMultipartFileCollection (Object object) {
if (!(object instanceof Iterable)) {
return false;
}
val iterable = (Iterable<?>) object;
val iterator = iterable.iterator();
return iterator.hasNext() && iterator.next() instanceof MultipartFile;
}
}
4. 接口使用
注意:接口上面要加 consumes = MediaType.MULTIPART_FORM_DATA_VALUE
@PostMapping(value = "test", consumes = MediaType.MULTIPART_FORM_DATA_VALUE)
ResponseResult<Boolean> replyNewMail(@RequestPart("files") MultipartFile[] multipartFiles,
@RequestParam("name") String name);