SpringCloud Feign多文件上传

/ java / 没有评论 / 147浏览

SpringCloud Feign多文件上传

问题

通过feign上传文件到其他服务,单个的MultipartFile file我们feign是可以正常接收到,但是如果传MultipartFile[] file的时候会报错

解决

通过查看源码,我们可以找到SpringFormEncoder这个类,在这个类里面我们可以看到encode 方法中它直接判断的了 MultipartFile.class,没有判断数组形式的,所以我们就需要修改一下这里。

public class SpringFormEncoder extends FormEncoder {
    public SpringFormEncoder() {
        this(new Default());
    }

    public SpringFormEncoder(Encoder delegate) {
        super(delegate);
        MultipartFormContentProcessor processor = (MultipartFormContentProcessor)this.getContentProcessor(ContentType.MULTIPART);
        processor.addWriter(new SpringSingleMultipartFileWriter());
        processor.addWriter(new SpringManyMultipartFilesWriter());
    }

    public void encode(Object object, Type bodyType, RequestTemplate template) throws EncodeException {
        if(!bodyType.equals(MultipartFile.class)) {
            super.encode(object, bodyType, template);
        } else {
            MultipartFile file = (MultipartFile)object;
            Map<String, Object> data = Collections.singletonMap(file.getName(), object);
            super.encode(data, MAP_STRING_WILDCARD, template);
        }
    }
}

首先我们创建一个类,SpringMultipartEncoder,重写encode方法:

import feign.RequestTemplate;
import feign.codec.EncodeException;
import feign.codec.Encoder;
import feign.form.MultipartFormContentProcessor;
import feign.form.spring.SpringFormEncoder;
import feign.form.spring.SpringManyMultipartFilesWriter;
import feign.form.spring.SpringSingleMultipartFileWriter;
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 kite
 * @version 1.0
 * @date 2020/7/13 18:41
 */
public class SpringMultipartEncoder extends SpringFormEncoder {

    public SpringMultipartEncoder(Encoder delegate) {
        super(delegate);
        MultipartFormContentProcessor processor = (MultipartFormContentProcessor) getContentProcessor(MULTIPART);
        processor.addWriter(new SpringSingleMultipartFileWriter());
        processor.addWriter(new SpringManyMultipartFilesWriter());
    }

    @Override
    public void encode(Object object, Type bodyType, RequestTemplate template) throws EncodeException {
        if (bodyType != null && bodyType.equals(MultipartFile[].class)) {
            MultipartFile[] file = (MultipartFile[]) object;
            if(file != null) {
                Map data = Collections.singletonMap(file.length == 0 ? "" : file[0].getName(), object);
                super.encode(data, MAP_STRING_WILDCARD, template);
                return;
            }
        }
        super.encode(object, bodyType, template);
    }
}

Encoder注入

public interface IFileFeignClient {

    @ApiOperation(value = "上传文件")
    @RequestMapping(value = "/sys/attachment/encrypt/uploads", method = RequestMethod.POST,  produces = MediaType.APPLICATION_JSON_UTF8_VALUE, consumes = MediaType.MULTIPART_FORM_DATA_VALUE)
    Result<List<Map<String, Object>>> uploads(@RequestPart(value = "files", required = false) MultipartFile[] files, @RequestParam(value = "typeCode", required = false) String typeCode);


    @Configuration
    class FeignMultipartSupportConfig {
        @Bean
        public Encoder feignEncoder(ObjectFactory<HttpMessageConverters> messageConverters) {
            return new SpringMultipartEncoder(new SpringEncoder(messageConverters));

        }
    }
}