springcloud 使用feign多文件上传
多文件上传
最近项目中遇到的问题,找了很多文档一直不成功。最后终于解决了springcloud间微服务调用时传多个文件的问题。
代码
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>
FeignSpringFormEncoder
package org.xxx.springcloud.config;
import feign.RequestTemplate;
import feign.codec.EncodeException;
import feign.codec.Encoder;
import feign.form.FormEncoder;
import feign.form.MultipartFormContentProcessor;
import feign.form.spring.SpringManyMultipartFilesWriter;
import feign.form.spring.SpringSingleMultipartFileWriter;
import lombok.val;
import org.springframework.web.multipart.MultipartFile;
import java.lang.reflect.Type;
import java.util.Collections;
import java.util.Map;
import static feign.form.ContentType.MULTIPART;
/**
* @author Xu Rui
* @date 2021/1/24 16:30
*/
public class FeignSpringFormEncoder extends FormEncoder {
/**
* Constructor with the default Feign's encoder as a delegate.
*/
public FeignSpringFormEncoder() {
this(new Encoder.Default());
}
/**
* Constructor with specified delegate encoder.
*
* @param delegate delegate encoder, if this encoder couldn't encode object.
*/
public FeignSpringFormEncoder(Encoder delegate) {
super(delegate);
val processor = (MultipartFormContentProcessor) getContentProcessor(MULTIPART);
processor.addFirstWriter(new SpringSingleMultipartFileWriter());
processor.addFirstWriter(new SpringManyMultipartFilesWriter());
}
@Override
public void encode(Object object, Type bodyType, RequestTemplate template) throws EncodeException {
if (bodyType.equals(MultipartFile.class)) {
MultipartFile file = (MultipartFile) object;
Map<String, Object> data = Collections.singletonMap(file.getName(), object);
super.encode(data, MAP_STRING_WILDCARD, template);
return;
} else if (bodyType.equals(MultipartFile[].class)) {
MultipartFile[] file = (MultipartFile[]) object;
if (file != null) {
Map<String, Object> data = Collections.singletonMap(file.length == 0 ? "" : file[0].getName(), object);
super.encode(data, MAP_STRING_WILDCARD, template);
return;
}
}
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;
}
}
MultipartSupportConfig
package org.xxx.springcloud.config;
import feign.codec.Encoder;
import org.springframework.beans.factory.ObjectFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.http.HttpMessageConverters;
import org.springframework.cloud.openfeign.support.SpringEncoder;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
/**
* @author Xu Rui
* @date 2021/1/22 22:52
*/
@Configuration
public class MultipartSupportConfig {
@Autowired
private ObjectFactory<HttpMessageConverters> messageConverters;
@Bean
public Encoder feignFormEncoder() {
return new FeignSpringFormEncoder(new SpringEncoder(messageConverters));
}
}
feign接口端
package org.xxx.springcloud.service;
import org.xxx.springcloud.config.MultipartSupportConfig;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.http.MediaType;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RequestPart;
import org.springframework.web.multipart.MultipartFile;
/**
* @author Xu Rui
* @date 2021/1/22 14:18
*/
@FeignClient(value = "CLOUD-SERVICE", configuration = MultipartSupportConfig.class)
public interface DataFeignService {
@PostMapping(value = "/data/upload", consumes = MediaType.MULTIPART_FORM_DATA_VALUE, produces = MediaType.APPLICATION_JSON_VALUE)
CommonResult<String> upload(@RequestParam("type") String type, @RequestPart("files") MultipartFile[] files);
}
controller服务消费者端
@PostMapping("/data/upload")
public CommonResult<String> uploadAlg( @RequestParam("type") String type, @RequestPart("files") MultipartFile[] files){
return dataFeignService.upload(type, files);
}
controller服务提供者端(被调用)
@PostMapping(value = "/data/upload")
public CommonResult<String> upload(@RequestParam("type") String type, @RequestParam("files") MultipartFile[] files) {
}