OpenFeign實(shí)現(xiàn)微服務(wù)間的文件下載方式
項(xiàng)目場(chǎng)景
微服務(wù)通過(guò)openfeign獲取文件流
問(wèn)題描述
微服務(wù)通過(guò)openfeign獲取文件流,消費(fèi)端獲取的inputSteam=null,無(wú)法獲取到文件流信息
解決方案
file服務(wù)(提供者)
根據(jù)附件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);
業(yè)務(wù)服務(wù)(消費(fèi)者)
將附件打包zip文件下載(附全部zip打包相關(guān)代碼,可直接看最后一個(gè)執(zhí)行壓縮的方法)
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(); // 設(shè)置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("導(dǎo)出壓縮包失敗"); } } } /** * 打壓縮包導(dǎo)出 */ 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("關(guān)閉zip輸出流失敗"); } } } } /** * 執(zhí)行壓縮 */ 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("執(zhí)行壓縮失敗"); } } } }
核心代碼
- 提供者:返回void,HttpServletResponse 寫入
- feign:應(yīng)用提供者接口,返回改為Response(用feign.Response來(lái)接收)
- 消費(fèi)者:調(diào)用feign,轉(zhuǎn)為InputStream
Response response = attachmentCilent.down(map); Response.Body body = response.body(); InputStream in = body.asInputStream();
總結(jié)
以上為個(gè)人經(jīng)驗(yàn),希望能給大家一個(gè)參考,也希望大家多多支持腳本之家。
相關(guān)文章
Servlet第一個(gè)項(xiàng)目的發(fā)布(入門)
這篇文章主要介紹了Servlet第一個(gè)項(xiàng)目的發(fā)布,下面是用servlet實(shí)現(xiàn)的一個(gè)簡(jiǎn)單的web項(xiàng)目,小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧2021-04-04JAVA匿名內(nèi)部類語(yǔ)法分析及實(shí)例詳解
這篇文章主要介紹了JAVA匿名內(nèi)部類語(yǔ)法分析及實(shí)例詳解,匿名內(nèi)部類可以使你的代碼更加簡(jiǎn)潔,它與局部類很相似,不同的是它沒(méi)有類名,如果某個(gè)局部類你只需要用一次,那么你就可以使用匿名內(nèi)部類。對(duì)此感興趣的可以了解一下2020-07-07SpringBoot2整合Drools規(guī)則引擎及案例詳解
這篇文章主要介紹了SpringBoot2整合Drools規(guī)則引擎及案例詳解,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2019-10-10Linux?Ubuntu系統(tǒng)下配置JDK環(huán)境、MySQL環(huán)境全過(guò)程
眾所周知Ubuntu是一種基于Linux的操作系統(tǒng),它提供了一個(gè)穩(wěn)定、安全和易于使用的環(huán)境,下面這篇文章主要給大家介紹了關(guān)于Linux?Ubuntu系統(tǒng)下配置JDK環(huán)境、MySQL環(huán)境的相關(guān)資料,文中通過(guò)代碼介紹的非常詳細(xì),需要的朋友可以參考下2024-07-07深入理解happens-before和as-if-serial語(yǔ)義
本文大部分整理自《Java并發(fā)編程的藝術(shù)》,溫故而知新,加深對(duì)基礎(chǔ)的理解程度。下面可以和小編來(lái)一起學(xué)習(xí)下2019-05-05IDEA2020.1啟動(dòng)SpringBoot項(xiàng)目出現(xiàn)java程序包:xxx不存在
這篇文章主要介紹了IDEA2020.1啟動(dòng)SpringBoot項(xiàng)目出現(xiàn)java程序包:xxx不存在,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2020-06-06