美文网首页
使用Feign接口实现文件上传的解决方案

使用Feign接口实现文件上传的解决方案

作者: kdyzm | 来源:发表于2023-11-05 16:27 被阅读0次

    原文链接:使用Feign接口实现文件上传的解决方案

    一般的情况下,后端有个微服务,暴露出一个文件上传的restful接口给前端,前端调用该接口获取上传后的链接以及oss key值完成上传。假设提供restful接口的这个服务叫做A,现在有个微服务B有个本地文件,需要将本地文件调用A文件文件上传接口上传到文件服务器,该如何做?

    一般情况下,一个文件上传的restful接口如下所示:

    @PostMapping("/upload")
    public WrapperResult<UploadResult> uploadFile(@RequestParam("file") MultipartFile multipartFile){
        ......
    }
    

    那对应的Feign接口就如下所示

    @PostMapping("/upload")
    public WrapperResult<UploadResult> uploadFile(@RequestParam("file") MultipartFile multipartFile);
    

    从直觉上来看,直接调用八成会出问题(笑),通过踩坑,我梳理了下后端调用Feign接口实现文件上传的改造点

    1. 接口修改

    一般的文件上传接口定义:

    @PostMapping("/upload")
    public WrapperResult<UploadResult> uploadFile(@RequestParam("file") MultipartFile multipartFile){
        ......
    }
    

    在Feign接口暴露出来的情况下,则不能再使用@RequestParam注解,应当使用@RequestPart注解,另外需要指定consumes类型为表单类型,否则会翻车。

    修改后的接口如下

     @PostMapping(
        value = {"/upload"},
        consumes = {"multipart/form-data"}
    )
    UploadResult uploadFile(@RequestPart("file") @NotNull MultipartFile multipartFile);
    

    这里注意两点:

    1. 使用@RequestPart注解替换掉@RequestParam注解
    2. 指定consumes类型为表单类型

    2. Encoder修改

    在springboot中,一般的Encoder定义如下

    @Bean
    @Primary
    public Encoder feignEncoder() {
        HttpMessageConverter jacksonConverter = new MappingJackson2HttpMessageConverter(
                JsonUtils.getObjectMapper()
        );
        ObjectFactory<HttpMessageConverters> objectFactory = 
                () -> new HttpMessageConverters(jacksonConverter);
        return new SpringEncoder(objectFactory);
    }
    

    返回了一个SpringEncoder对象,这里需要返回一个SpringFormEncoder对象以支持Feign接口的表单功能,只需要将new SpringEncoder(objectFactory)修改为new SpringFormEncoder(new SpringEncoder(objectFactory))即可,修改后的代码如下

    @Bean
    @Primary
    public Encoder feignEncoder() {
        HttpMessageConverter jacksonConverter = new MappingJackson2HttpMessageConverter(
                JsonUtils.getObjectMapper()
        );
        ObjectFactory<HttpMessageConverters> objectFactory = 
                () -> new HttpMessageConverters(jacksonConverter);
        return new SpringFormEncoder(new SpringEncoder(objectFactory));
    }
    

    3. 客户端调用修改

    现在Feign接口长这个样子

     @PostMapping(
        value = {"/upload"},
        consumes = {"multipart/form-data"}
    )
    UploadResult uploadFile(@RequestPart("file") @NotNull MultipartFile multipartFile);
    

    那我们Feign接口调用的时候就得构造MultipartFile对象,这里需要引入spring-test的依赖

    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-test</artifactId>
    </dependency>
    

    然后代码这么写

    FileInputStream fis = null;
    try {
        Tika tika = new Tika();
        String mimeType = tika.detect(file);
        fis = new FileInputStream(file);
        MockMultipartFile mockMultipartFile = new MockMultipartFile(
                "file",
                file.getName(),
                mimeType,
                fis
        );
    
        UploadResult uploadResult = ossPublicApi.uploadFile(mockMultipartFile);
    }catch(Exception e){
        ......
    }
    

    这里为了告知正确的媒体类型,引入了tika,关于tika,参考文章 使用tika获取文件的实际类型 引入

    需要注意以下几点

    1. 需要引入spring-test,注意scope默认就行,不能为provided
    2. 需要引入tika,告知正确的媒体类型,否则上传到minio等文件服务器,在浏览器中打开图片、mp4视频等文件本来应当在浏览器打开的文件会变成自动下载

    END.

    相关文章

      网友评论

          本文标题:使用Feign接口实现文件上传的解决方案

          本文链接:https://www.haomeiwen.com/subject/wjozidtx.html