解决微服务Feign 接口之间文件传递问题

564 阅读1分钟

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);