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();

总结

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

相关文章

  • Mybatis中多个对象包含同一个对象的处理操作

    Mybatis中多个对象包含同一个对象的处理操作

    这篇文章主要介绍了Mybatis中多个对象包含同一个对象的处理操作,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2021-06-06
  • java字符串转数字及各种数字转字符串的3种方法

    java字符串转数字及各种数字转字符串的3种方法

    这篇文章主要介绍了java字符串转数字及各种数字转字符串的3种方法,本文通过实例代码给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2023-09-09
  • RabbitMq消息防丢失功能实现方式讲解

    RabbitMq消息防丢失功能实现方式讲解

    这篇文章主要介绍了RabbitMq消息防丢失功能实现,RabbitMQ中,消息丢失可以简单的分为两种:客户端丢失和服务端丢失。针对这两种消息丢失,RabbitMQ都给出了相应的解决方案
    2023-01-01
  • java RocketMQ快速入门基础知识

    java RocketMQ快速入门基础知识

    这篇文章主要介绍了java RocketMQ快速入门基础知识,所以RocketMQ是站在巨人的肩膀上(kafka),又对其进行了优化让其更满足互联网公司的特点。它是纯Java开发,具有高吞吐量、高可用性、适合大规模分布式系统应用的特点。,需要的朋友可以参考下
    2019-06-06
  • java实现在性能测试中进行业务验证实例

    java实现在性能测试中进行业务验证实例

    这篇文章主要为大家介绍了java实现在性能测试中进行业务验证实例,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2022-07-07
  • JDK源码中一些实用的“小技巧”总结

    JDK源码中一些实用的“小技巧”总结

    这篇文章主要给大家总结介绍了关于JDK源码中一些实用的“小技巧”,文中通过示例代码介绍的非常详细,对大家学习或者使用jdk源码具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧。
    2018-03-03
  • 介绍Java的大数类(BigDecimal)和八种舍入模式

    介绍Java的大数类(BigDecimal)和八种舍入模式

    在实际应用中,需要对更大或者更小的数进行运算和处理。Java在java.math包中提供的API类BigDecimal,用来对超过16位有效位的数进行精确的运算。本文将介绍Java中的大数类BigDecimal及其八种舍入模式,有需要的可以参考借鉴。
    2016-08-08
  • Java遍历Json中的key和value问题

    Java遍历Json中的key和value问题

    这篇文章主要介绍了Java遍历Json中的key和value问题,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教
    2023-11-11
  • spring security登录成功后通过Principal获取名返回空问题

    spring security登录成功后通过Principal获取名返回空问题

    这篇文章主要介绍了spring security登录成功后通过Principal获取名返回空问题,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教
    2024-03-03
  • Java 中二进制转换成十六进制的两种实现方法

    Java 中二进制转换成十六进制的两种实现方法

    这篇文章主要介绍了Java 中二进制转换成十六进制的两种实现方法的相关资料,需要的朋友可以参考下
    2017-06-06

最新评论