使用feign接口实现文件上传

yuyu888 于 2023-01-12 发布

场景

开发框架使用spring cloud 微服务体系,微服务之间调用使用的是feign接口调用,我这边又开发了一个file-service 实现文件上传存储,文件转化等服务,需要feign接口能实现文件上传 能够收 @RequestParam(“file”) MultipartFile file参数

急切之间在网上找到了以下方法

解决办法

配置一个SpringFormEncoder

//@Configuration 千万别删除, 否则全局生效
public class FeignMultipartSupportConfig {
    @Bean
    @Primary
    @Scope("prototype")
    public SpringFormEncoder multipartFormEncoder() {
        return new SpringFormEncoder();
    }

}

请注意这句话–“//@Configuration 千万别删除, 否则全局生效” 之前在网上摘录的时候, 没注意, 直接拷过来, 结果其他的feignApi都出问题了

feign Api

@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class FileUploadForm {
    private MultipartFile file;
    private String businessType;
    private String customPath;
}


@FeignClient(name = "fileservice", path = "/file-service/serviceapi/file", contextId= "fileservice", configuration = FeignMultipartSupportConfig.class, decode404 = true)
public interface FileService {
    @RequestMapping("/info/{id}")
    public UploadResponseVo info(@PathVariable("id") Integer id);

    @PostMapping(value="/common-upload", consumes = {MediaType.MULTIPART_FORM_DATA_VALUE})
    public UploadResponseVo commonUpload(FileUploadForm form);

    @RequestMapping("/multiple-data")
    public List<UploadResponseVo> multipleData(@RequestParam("ids") List<Integer> ids);

    @GetMapping("/mytest")
    public String mytest();

}

这里 FeignMultipartSupportConfig 不要用@Configuration 这个注解, 在对应的feigin上使用 configuration = FeignMultipartSupportConfig.class,可以解决不同的feign interface 配置隔离,不影响其他feign接口的编码器

不过比该方法会导致 name = “fileservice”的所有微服务接口都 受到 这个 SpringFormEncoder 影响, 无法实现 上传 与 @RequestBody 传参兼容, 引起的 “xx is not a type supported by this encoder.” 错误

终极方案

经过多次研究测试后,发现只需要在请求头里面加上文件上传的CONTENT_TYPE即可:

conten-type=multipart/form-data

spring 默认的 FeignClientsConfiguration 中的 PageableSpringEncoder 已经支持文件上传了。

public interface FileService {
    @PostMapping(value = "/upload", headers = "content-type=" + MediaType.MULTIPART_FORM_DATA_VALUE)
    String upload(@RequestPart("file") MultipartFile file);
}