文章目录
- 前言
- 一、feign接口获取文件流程:
- 二、文件获取实现
- 2.1 引入jar:
- 2.2 实现:
- 总结
前言
通常在spring-boot 项目中,对于文件的下载都是直接调用到对应的服务中,而不是通过feign 接口获取文件;有时我们在对接外部接口时,因为权限等问题,不能直接暴露文件服务,会有一个专门对外的服务进行对接,但是我们又要利用现有的文件服务逻辑,此时可以考虑使用feign 完成文件的获取。
一、feign接口获取文件流程:
我们知道feign 只是通过动态代理为我们构建了http 的请求,显然我们不能通过feign 接口直接把 HttpServletResponse 传过去,因为feign接口服务的提供者,接收到的HttpServletResponse 和我们通过feign 接口传入的压根儿就不是同一个对象,所以此时我们只能在文件服务中返回文件流,然后在将文件流 写入到最开始HttpServletResponse 对象中,最后返回给浏览器,流程大概如下:
二、文件获取实现
2.1 引入jar:
因为我们是web 服务并且使用了feign 接口所有这个两个jar 依赖是必须要有的:
<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>
2.2 实现:
(1) feign 接口:
@GetMapping(value = "/osp/download/{id}", produces = MediaType.APPLICATION_OCTET_STREAM_VALUE)
ResponseEntity<Resource> download(@PathVariable("id") String id);
(2)feign 接口服务提供者:
控制器:
import org.springframework.core.io.Resource;
import org.springframework.http.ResponseEntity;@GetMapping("/osp/download/{id}")public ResponseEntity<Resource> ospDownloadFile(@PathVariable String id) throws Exception {return xxxService.ospDownloadFile(id);}
xxxService 对应自己业务里面的实现;实现类:
@Override
public ResponseEntity<org.springframework.core.io.Resource> ospDownloadFile(String id) throws Exception {// 这里获取自己业务中的文件FileRecord fileRecord = fileRecordService.selectCache(id);if (null == fileRecord)throw new Exception("文件不存在");InputStream inputStream = null;ByteArrayOutputStream outputStream = null;try {inputStream = getObjectInputStream(fileRecord.getCodeName());outputStream = new ByteArrayOutputStream();byte[] buffer = new byte[1024];int length;while ((length = inputStream.read(buffer)) != -1) {outputStream.write(buffer, 0, length);}byte[] byteArray = outputStream.toByteArray();// 读取文件内容ByteArrayResource resource = new ByteArrayResource(byteArray);// 设置响应头HttpHeaders headers = new HttpHeaders();headers.add(HttpHeaders.CONTENT_DISPOSITION, "attachment; filename=" + java.net.URLEncoder.encode(fileRecord.getName(),"UTF-8"));// 返回响应实体return ResponseEntity.ok().headers(headers).contentType(MediaType.APPLICATION_OCTET_STREAM).body(resource);} finally {if (null != inputStream) {inputStream.close();}if (null != outputStream) {outputStream.close();}}}
(3)对外服务端:
对外服务控制器:
@GetMapping("/file/download/{id}")
public void download(@PathVariable String id,HttpServletResponse response) throws Exception {ospFlowService.ospDownLoadFile(id,response);
}
业务实现类:
@Override
public void ospDownLoadFile(String id, HttpServletResponse response) throws Exception {// feign 接口获取文件流ResponseEntity<Resource> fileResponse = remoteFileService.download(id);// 设置响应头response.setHeader(HttpHeaders.CONTENT_DISPOSITION, fileResponse.getHeaders().get(HttpHeaders.CONTENT_DISPOSITION).get(0));response.setContentType(MediaType.APPLICATION_OCTET_STREAM_VALUE);// 从 Feign 响应中获取文件输入流,并写入到 HttpServletResponse 输出流中InputStream inputStream = fileResponse.getBody().getInputStream();OutputStream output = response.getOutputStream();IoUtil.copy(inputStream, output);// 将流刷新给到浏览器response.flushBuffer();}
这里使用cn.hutool.core.io 中的 IoUtil 工具类,有需要的可以引入
<dependency><groupId>cn.hutool</groupId><artifactId>hutool-all</artifactId>
</dependency>
总结
本文通过feign 接口完成文件的下载。