zoukankan      html  css  js  c++  java
  • 解决OpenFeign无法上传文件的问题

    前言

      最近在项目中使用OpenFeign时,发现其不支持文件上传功能。网上找了很多资料,最后找到feign-form和feign-form-spring的解决方案。但其默认只支持单文件上传,不支持多文件上传。解决办法为:重写Encoder类,详见三。

    一、配置

    1. 引入依赖

    <dependency>
        <groupId>io.github.openfeign.form</groupId>
        <artifactId>feign-form</artifactId>
        <version>3.3.0</version>
    </dependency>
    <dependency>
        <groupId>io.github.openfeign.form</groupId>
        <artifactId>feign-form-spring</artifactId>
        <version>3.3.0</version>
    </dependency>

    2. 在调用方增加配置

    @Configuration
    public class AdminWebMvcConfig implements WebMvcConfigurer {
        @Bean
        public Encoder feignFormEncoder(ObjectFactory<HttpMessageConverters> messageConverters) {
            return new SpringFormEncoder(new SpringEncoder(messageConverters));
        }
    }

    3. 调用方启动类配置

    @EnableFeignClients(basePackages = {"com.xxx.xxx"})
    @SpringCloudApplication
    @Import({AdminWebMvcConfig.class})
    public class WebAdminApplication {
    
        public static void main(String[] args) {
            SpringApplication.run(WebAdminApplication.class, args);
        }
    
    }

    二、单文件上传代码实现

    • 服务调用方、接口和提供方,都使用@RequestPart注解
    • 标记MediaType.MULTIPART_FORM_DATA_VALUE

    1. 服务提供方Controller

    @PostMapping(value = "/upload", consumes = MediaType.MULTIPART_FORM_DATA_VALUE)
    @ResponseBody
    public String upload(@RequestPart(value = "file") MultipartFile file) {
    
      ......
    }

    2. FeignClient接口

    @FeignClient(name = "xxx")
    public interface FileUploadApiClient {
      /**
      * 文件上传
      */
      @PostMapping(value = "/oss/upload", consumes = MediaType.MULTIPART_FORM_DATA_VALUE)
      String upload(@RequestPart(value = "file") MultipartFile file);
    
    }

    3. 调用方Controller

    @RestController
    public class FileUploadManagerController {
    
      @Autowired
      private FileUploadApiClient fileUploadApiClient;
    
      @PostMapping(value = "/upload", consumes = MediaType.MULTIPART_FORM_DATA_VALUE)
      @ResponseBody
      public String upload(@RequestPart(value = "file") MultipartFile file) {
        return fileUploadApiClient.upload(file);
      }
    }

    三、多文件上传实现

    •  只需修改下面两项,即可完美支持单文件和多文件上传功能

    1. 新建FeignSpringFormEncoder类

    import feign.RequestTemplate;
    import feign.codec.EncodeException;
    import feign.codec.Encoder;
    import feign.form.ContentType;
    import feign.form.FormEncoder;
    import feign.form.MultipartFormContentProcessor;
    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;
    
    public class FeignSpringFormEncoder extends FormEncoder {
     
        /**
         * Constructor with the default Feign's encoder as a delegate.
         */
        public FeignSpringFormEncoder() {
            this(new Default());
        }
    
     
        /**
         * Constructor with specified delegate encoder.
         *
         * @param delegate delegate encoder, if this encoder couldn't encode object.
         */
        public FeignSpringFormEncoder(Encoder delegate) {
            super(delegate);
    
            MultipartFormContentProcessor processor = (MultipartFormContentProcessor) getContentProcessor(ContentType.MULTIPART);
            processor.addWriter(new SpringSingleMultipartFileWriter());
            processor.addWriter(new SpringManyMultipartFilesWriter());
        }
     
     
        @Override
        public void encode(Object object, Type bodyType, RequestTemplate template) throws EncodeException {
            if (bodyType.equals(MultipartFile.class)) {
                MultipartFile file = (MultipartFile) object;
                Map 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 data = Collections.singletonMap(file.length == 0 ? "" : file[0].getName(), object);
                    super.encode(data, MAP_STRING_WILDCARD, template);
                    return;
                }
            }
            super.encode(object, bodyType, template);
        }
    }

    2. 修改AdminWebMvcConfig 

    @Configuration
    public class AdminWebMvcConfig implements WebMvcConfigurer {
    
        @Bean
        public Encoder feignEncoder(ObjectFactory<HttpMessageConverters> messageConverters) {
            return new FeignSpringFormEncoder(new SpringEncoder(messageConverters));
        }
    }

    参考:https://blog.csdn.net/ytzzh0726/article/details/79467843

  • 相关阅读:
    课题:快速建立自己的外链资源圈
    【干货分享】常用端口服务对照表
    【经验分享(续篇)】Trachtenberg system(特拉亨伯格速算系统)
    网站渗透测试原理及详细过程
    渗透测试入门DVWA 教程1:环境搭建
    CTF---密码学入门第七题 杯酒人生
    CTF---密码学入门第六题 古典密码
    CTF---密码学入门第五题 传统知识+古典密码
    CTFCrackTools在Windows下显示A Java Exception has occurred的解决方案
    CTF---密码学入门第四题 困在栅栏里的凯撒
  • 原文地址:https://www.cnblogs.com/wslook/p/9341038.html
Copyright © 2011-2022 走看看