OpenFeign实现微服务间的文件下载方式
作者:Mr-Wanter
这篇文章主要介绍了OpenFeign实现微服务间的文件下载方式,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教
项目场景
微服务通过openfeign获取文件流
问题描述
微服务通过openfeign获取文件流,消费端获取的inputSteam=null,无法获取到文件流信息
解决方案
file服务(提供者)
根据附件id,获取附件路径下载
@ApiOperation(value = "附件下载") @RequestMapping(value = "/file/download/v1", method = RequestMethod.POST,consumes = MediaType.APPLICATION_JSON_UTF8_VALUE) public void down(HttpServletResponse response,@CustomJSONBody Object object) { Map<String, String> map = (Map) object; String fileId = map.get("fileId"); String[] fileInfos = attachmentService.findById(fileId); InputStream in = null; try { String filePath = fileUploadDir + fileInfos[1]; if (File.separator.equals("/")) { filePath = filePath.replaceAll("\\\\", File.separator); } else if (File.separator.equals("\\\\")) { filePath = filePath.replaceAll("/", File.separator); } in = new FileInputStream(filePath); OutputStream out = response.getOutputStream(); byte buffer[] = new byte[1024]; int length = 0; while ((length = in.read(buffer)) >= 0){ out.write(buffer,0,length); } } catch (Exception e) { logger.error("附件下载异常", e); } finally { if(in != null){ try { in.close(); } catch (IOException e) { e.printStackTrace(); } } } }
feign
@RequestMapping(value = "/file/download/v1", method = RequestMethod.POST,consumes = MediaType.APPLICATION_JSON_UTF8_VALUE) public Response down(@CustomJSONBody Object object);
业务服务(消费者)
将附件打包zip文件下载(附全部zip打包相关代码,可直接看最后一个执行压缩的方法)
public void zipExcelExport(DisasterHistoryExportDTO dto, HttpServletResponse response) { List<String> ids = dto.getList().stream().map(DisasterExpandPO::getFileId).collect(Collectors.toList()); List<AttachmentPO> attachmentPOList = attachmentDao.findAllById(ids); if (CollectionUtils.isNotEmpty(attachmentPOList)) { try { response.reset(); // 设置response的Header String exportName = URLEncoder.encode(dto.getFileName() + ".zip", "utf-8"); response.setContentType("application/octet-stream"); response.setCharacterEncoding("utf-8"); response.setHeader("Content-Disposition", "attachment; filename=" + exportName); response.setHeader("FileName", exportName); response.setHeader("Access-Control-Expose-Headers", "FileName"); OutputStream out = response.getOutputStream(); excelsToZip(out, attachmentPOList); out.close(); } catch (IOException ex) { throw new BusinessException("导出压缩包失败"); } } } /** * 打压缩包导出 */ private void excelsToZip(OutputStream out, List<AttachmentPO> list) throws RuntimeException { ZipOutputStream zos = null; try { zos = new ZipOutputStream(out); compressExcel(zos, list); } catch (Exception e) { throw new RuntimeException("zip error from ZipUtils", e); } finally { if (zos != null) { try { zos.close(); } catch (IOException e) { throw new BusinessException("关闭zip输出流失败"); } } } } /** * 执行压缩 */ private void compressExcel(ZipOutputStream zos, List<AttachmentPO> list) { if (CollectionUtils.isNotEmpty(list)) { for (AttachmentPO item : list) { byte[] buf = new byte[BUFFER_SIZE]; Map<String, String> map = new HashMap<>(); map.put("fileId", item.getAttachId()); Response response = attachmentCilent.down(map); Response.Body body = response.body(); try { InputStream in = body.asInputStream(); zos.putNextEntry(new ZipEntry(item.getOldName())); int len; while ((len = in.read(buf)) != -1) { zos.write(buf, 0, len); } zos.closeEntry(); in.close(); in.close(); } catch (IOException e) { throw new BusinessException("执行压缩失败"); } } } }
核心代码
- 提供者:返回void,HttpServletResponse 写入
- feign:应用提供者接口,返回改为Response(用feign.Response来接收)
- 消费者:调用feign,转为InputStream
Response response = attachmentCilent.down(map); Response.Body body = response.body(); InputStream in = body.asInputStream();
总结
以上为个人经验,希望能给大家一个参考,也希望大家多多支持脚本之家。