Spring Cloud Feign 文件传输
微服务中通常使用 Feign 作为服务消费者,那么如何使用 Feign 接口传输文件呢?
一、配置文件解析器
服务提供者和消费者都需要配置文件解析器,这里使用commons-fileupload替换原有的解析器:
依赖:
1<dependency>
2 <groupId>commons-fileupload</groupId>
3 <artifactId>commons-fileupload</artifactId>
4 <version>1.3.1</version>
5</dependency>
注入bean:
1@Bean(name = "multipartResolver")
2public MultipartResolver mutipartResolver() {
3 CommonsMultipartResolver com = new CommonsMultipartResolver();
4 com.setDefaultEncoding("utf-8");
5 return com;
6}
程序入口中剔除原有的解析器:
1@SpringBootApplication(exclude = {MultipartAutoConfiguration.class})
二、服务提供者,即接收文件一方的配置
Controller的写法:
1@ResponseBody
2@RequestMapping(value = "/upload", method = {RequestMethod.POST},
3 produces = {MediaType.APPLICATION_JSON_UTF8_VALUE},
4 consumes = MediaType.MULTIPART_FORM_DATA_VALUE)
5public Result<String> uploadFile(@RequestPart("file") MultipartFile file,
6 @RequestParam("id") Long id) {
7 String fileName = file.getOriginalFilename();
8 String extend = FileOperateUtil.suffix(fileName);
9 FileOperateUtil.copy("E:\\" + fileName, file);
10 return ResultBuilder.success("ok");
11}
@RequestPart指定文件,后面的@RequestParam是额外参数,注意额外参数不能超过url长度限制。
三、服务消费者配置
依赖:
1<dependency>
2 <groupId>io.github.openfeign.form</groupId>
3 <artifactId>feign-form-spring</artifactId>
4 <version>3.2.2</version>
5</dependency>
6<dependency>
7 <groupId>io.github.openfeign.form</groupId>
8 <artifactId>feign-form</artifactId>
9 <version>3.2.2</version>
10</dependency>
文件编码配置:
1import feign.codec.Encoder;
2import feign.form.spring.SpringFormEncoder;
3import org.springframework.beans.factory.ObjectFactory;
4import org.springframework.beans.factory.annotation.Autowired;
5import org.springframework.boot.autoconfigure.web.HttpMessageConverters;
6import org.springframework.cloud.netflix.feign.support.SpringEncoder;
7import org.springframework.context.annotation.Bean;
8import org.springframework.context.annotation.Configuration;
9
10@Configuration
11public class MultipartSupportConfig {
12
13 @Autowired
14 private ObjectFactory<HttpMessageConverters> messageConverters;
15
16 @Bean
17 public Encoder feignFormEncoder() {
18 return new SpringFormEncoder(new SpringEncoder(messageConverters));
19 }
20
21}
Feign接口定义:
1@FeignClient(name = "test-upload")
2public interface UploadService {
3
4 @ResponseBody
5 @RequestMapping(value = "/upload", method = {RequestMethod.POST},
6 produces = {MediaType.APPLICATION_JSON_UTF8_VALUE},
7 consumes = MediaType.MULTIPART_FORM_DATA_VALUE)
8 Result<String> uploadFile(@RequestPart("file") MultipartFile file,
9 @RequestParam("id") Long id);
10
11}
与普通Feign接口写法差不多,注意方法注解和参数与服务提供者的controller一样。
Controller的写法,Controller中接收前端传过来的文件信息和额外参数,然后通过Feign接口传输到远端:
1
2// 注入 feign 接口
3@Autowired
4private UploadService uploadService;
5
6@RequestMapping(value = "/upload", method = RequestMethod.POST, produces = "application/json; charset=utf-8")
7@ResponseBody
8public Result<String> testUpload(HttpServletRequest request, Long id) {
9 Result<String> result = null;
10 MultipartHttpServletRequest mRequest = (MultipartHttpServletRequest) request;
11 Map<String, MultipartFile> fileMap = mRequest.getFileMap();
12 for (MultipartFile mFile : fileMap.values()) {
13 String fileName = mFile.getOriginalFilename();
14 result = uploadService.uploadFile(mFile, id);
15 }
16 return result;
17}
四、总结
最后梳理一下流程,服务消费者接收前端(如浏览器)传过来的文件,但是并不进行业务处理,然后通过Feign调用接口,把文件传给服务提供者,服务提供者拿到文件后,进行相应的业务处理。
