OpenFeign实现微服务间的文件下载方式

 更新时间:2024年05月06日 09:45:38   作者: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();

总结

以上为个人经验,希望能给大家一个参考,也希望大家多多支持脚本之家。

相关文章

  • DispatcherServlet处理器的适配和处理解析

    DispatcherServlet处理器的适配和处理解析

    这篇文章主要为大家介绍了DispatcherServlet的处理器的适配和处理流程,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2023-06-06
  • Java并发编程之线程中断

    Java并发编程之线程中断

    这篇文章主要介绍了Java并发编程线程中断,java线程中断是一种线程间的协作模式,通过设置线程的中断标志并不能直接终止该线程的运行,而是被中断的线程根据中断状态自行处理,需要的朋友可以参考一下
    2021-09-09
  • 使用Maven打包时包含资源文件和源码到jar的方法

    使用Maven打包时包含资源文件和源码到jar的方法

    这篇文章主要介绍了使用Maven打包时包含资源文件和源码到jar的方法,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2022-08-08
  • springboot+hutool批量生成二维码压缩导出功能

    springboot+hutool批量生成二维码压缩导出功能

    这篇文章主要介绍了springboot+hutool批量生成二维码压缩导出功能,本文通过实例代码给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2021-10-10
  • activemq整合springboot使用方法(个人微信小程序用)

    activemq整合springboot使用方法(个人微信小程序用)

    这篇文章主要介绍了activemq整合springboot使用(个人微信小程序用),文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2019-03-03
  • Java内部类的使用教程详解

    Java内部类的使用教程详解

    在Java中,有些类可以被定义在另一个类的内部,我们把在一个类里面定义的类称为内部类。本文主要介绍了Java内部类的使用,需要的可以参考一下
    2023-04-04
  • 使用Spring的ApplicationEvent实现本地事件驱动的实现方法

    使用Spring的ApplicationEvent实现本地事件驱动的实现方法

    本文介绍了如何使用Spring的ApplicationEvent实现本地事件驱动,通过自定义事件和监听器,实现模块之间的松耦合,提升代码的可维护性和扩展性。同时还介绍了异步事件和事件传递的相关知识
    2023-04-04
  • SpringBoot使用外置Tomcat的操作步骤

    SpringBoot使用外置Tomcat的操作步骤

    这篇文章主要介绍了Spring Boot如何使用外置Tomcat,包括创建Maven Web项目、修改为Spring Boot项目、配置外部Tomcat和启动外部Tomcat,需要的朋友可以参考下
    2026-02-02
  • 使用MyEclipse 开发struts2框架实现登录功能(结构教程)

    使用MyEclipse 开发struts2框架实现登录功能(结构教程)

    这篇文章主要介绍了使用MyEclipse 开发struts2框架实现登录功能(结构教程)的相关资料,需要的朋友可以参考下
    2016-03-03
  • logback和log4j日志框架堆栈信息添加TraceId方式

    logback和log4j日志框架堆栈信息添加TraceId方式

    这篇文章主要介绍了logback和log4j日志框架堆栈信息添加TraceId方式,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教
    2023-09-09

最新评论