关于feign声明式服务调用实现文件上传和下载:
记得编写feign服务调用的回调方法,便于发现过程中报告的异常。
- 上传为post请求
- 异常:Current request is not a multipart request ,将参数注解将@RequestParam 更换为 @RequestPart
- 异常:No serializer found for class java.io.FileDescriptor,指定处理请求的提交内容类型consumes = MediaType.MULTIPART_FORM_DATA_VALUE
- 异常:no suitable HttpMessageConverter found for request type [[Lorg.springframework.web.multipart.MultipartFile;],说明结果json转换的时候的异常,增加FeignMultipartSupportConfig配置类
- 异常:Could not resolve view with name 'd/dealfile/wordpre/upload' in servlet,上传和下载不需要返回视图,记得使用@Response注解表明该接口的返回类型
- 异常:the field file exceeds its maximum permitted size of,SpringBoot嵌入的tomcat限制了请求的文件大小,需要设置spring.servlet.multipart.maxFileSize和spring.servlet.multipart.maxRequestSize
- 关于文件下载,我们在client中将文件写入响应流中,使用feign自带的Response对象接收,再通过设置响应体的信息完成下载
- 以上每一步的错误都是在编写的过程中发现的,至于为何这样解决,大家可以自行去查找每一步的原因
服务调用方:
@PostMapping("upload")
public void upload(@RequestParam("file") MultipartFile[] file){
uploadClient.upload(file);
}
@GetMapping("download")
public void download(HttpServletRequest request, HttpServletResponse response){
Response download = uploadClient.download();
Response.Body body = download.body();
try {
String fileName = "aaaaa.doc";
String name = new String(fileName.getBytes(), "iso8859-1");
response.setContentType("application/msword");//若为excel(application/msexcel)
response.setHeader("Content-disposition", "attachment;filename=" + name);
ServletOutputStream outputStream = response.getOutputStream();
InputStream fileInputStream = body.asInputStream();
byte[] bytes = new byte[1024];
int len = 0;
while ((len = fileInputStream.read(bytes)) != -1) {
outputStream.write(bytes, 0, len);
}
} catch (Exception e){
e.printStackTrace();
}
}
feign接口声明:
@Component
@FeignClient(value = "system-dealfile",contextId = "UploadClient",fallbackFactory = UploadFallback.class)
public interface UploadClient {
@PostMapping(value="/d/dealfile/wordpre/upload",consumes = MediaType.MULTIPART_FORM_DATA_VALUE)
@ResponseBody
public void upload(@RequestPart("file") MultipartFile[] file);
@GetMapping(value="/d/dealfile/wordpre/download",consumes = MediaType.APPLICATION_JSON_UTF8_VALUE)
@ResponseBody
public feign.Response download();
}
接口提供方:
@PostMapping("/d/dealfile/wordpre/upload")
public void upload(@RequestParam("file") MultipartFile[] file){
String path = "D:\\kjgh\\a.docx";
File t = new File(path);
try {
file[0].transferTo(t);
} catch (IOException e) {
e.printStackTrace();
}
}
@GetMapping(value = "/d/dealfile/wordpre/download",consumes = MediaType.APPLICATION_JSON_UTF8_VALUE)
public void download(HttpServletRequest request, HttpServletResponse response){
String path = "D:\\kjgh\\测试.docx";
try {
InputStream is = new FileInputStream(new File(path));
XWPFDocument doc = new XWPFDocument(is);
ServletOutputStream outputStream = null;
try {
String fileName = "下载文档.doc";
String name = new String(fileName.getBytes(), "iso8859-1");
response.setContentType("application/msword");//若为excel(application/msexcel)
response.setHeader("Content-disposition", "attachment;filename=" + name);
outputStream = response.getOutputStream();
doc.write(outputStream);
} catch (IOException e) {
e.printStackTrace();
}
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
FeignMultipartSupportConfig:
@Configuration
public class FeignMultipartSupportConfig {
@Bean
@Primary
@Scope("prototype")
public Encoder multipartFormEncoder() {
return new SpringFormEncoder();
}
@Bean
public feign.Logger.Level multipartLoggerLevel() {
return feign.Logger.Level.FULL;
}
}