需求场景:

接到一个需求,总结下来的核心要点是,要求下载一个zip文件,经过一些列业务分类之后,这个下载下来的zip包里面可能还有zip包,但是服务器上的原始文件都是word和excel这样的文件,也就是需要在代码段进行一个嵌套或者说递归打包的过程。

实际上就是需要一个类似这样的目录层级:

附件.zip

-第一个内部附件.zip

-工作记录.xls


问题分析:

1、首先常规的把全部附件打到一个压缩包,或者是带文件夹层级的都很常见,但是想嵌套成zip包,这个没有尝试过。

2、百度之后也无果,都是复制粘贴后最简单的压缩和解压缩,也就是单层的zip包压缩,并没有找到什么有效的方法,那没办法,得自己想

3、先分析常规的打包是怎么做的,我这边是http下载请求,就是通过ZipOutputStream把文件流输出到http的response中的输出流中去,而ZipOutputStream又是通过一个个ZipEntry对象和文件的inputStream流去写入数据

4、有了上面一层的理解就很简单了,其实只需要把内部打包的ZipOutputStream直接往外部的ZipOutputStream里面输出就可以了,我们只需要在外面把文件名定义好就可以了


代码:

void testExport(HttpServletResponse response){//下载的文件名String fileName="附件.zip";try {//根据自己前端以及浏览器设置文件名编码fileName = URLEncoder.encode(fileName,"UTF-8");} catch (Exception e) {log.error(e.getMessage(),e);}//设置响应头编码response.setContentType("application/octet-stream;charset=UTF-8");response.setCharacterEncoding("utf-8");//设置文件名response.setHeader("Content-Disposition","attachment;filename="+fileName);//把Content-Disposition这个字段开放给前端可见,这样前端就可以取到后端生成的文件名response.setHeader("Access-Control-Expose-Headers","Content-Disposition");//真正的下载,这里都是用的jdk7的写法,所有的流都不用我手动关闭了try (//这里面为了防止内存溢出等问题,使用了BufferedOutputStream缓冲流,可以看到这里是把流输出到了response里面ZipOutputStream zos1=new ZipOutputStream(new BufferedOutputStream(response.getOutputStream()), StandardCharsets.UTF_8);){zos1.setMethod(ZipOutputStream.DEFLATED);zos1.putNextEntry(new ZipEntry("第一个内部压缩包.zip"));try (//这里才是嵌套压缩的重点,可以看到这里zos2里面的输出流是zos1,这样,在内部处理的时候只需要处理zos2就行了,输出的操作会由zos2自己往zos里面输出ZipOutputStream zos2=new ZipOutputStream(new BufferedOutputStream(zos1), StandardCharsets.UTF_8);){//这里面内层压缩包的附件zos2.setMethod(ZipOutputStream.DEFLATED);zos2.putNextEntry(new ZipEntry("工作记录.xls"));try (InputStream is = new FileInputStream("data/工作记录.xls")){int b;byte[] buffer = new byte[1024];while ((b=is.read(buffer))!=-1){zos2.write(buffer,0,b);}zos2.flush();}catch (Exception e){log.error("文件输出异常",e);}}catch (Exception e){log.error("内部打包异常",e);}zos1.flush();}catch (Exception e){log.error("文件下载失败",e);}}

中间的一些思考过程:

1、其实一开始想错了,总在想一个output没办法往另一个output里面去写,甚至考虑过把output转为input,再写入到最外层的zipoutputstram中去,但是因为这个业务场景文件后期是会不断增多的,把全部的流放到内存中去大概率是会出问题的。

2、然后就想利用服务器做缓存,先把打包好的文件保存到服务器中去,然后再去直接读文件拿到输入流,但是这样一个是我觉得一个是增加io的压力,临时文件也得去清理;还有一个考虑到这样就失去了边压缩边下载的速度了。

3、后面才研究一下这个打包的过程,发现并不难实现,只是网上没有类似的内容,还是得去好好学习io的知识才可以

java实现压缩包嵌套压缩包的下载相关推荐

  1. java解析zip格式压缩包

    java解析zip格式压缩包 做项目时遇到需要将zip格式的压缩包解析里面的图片 将里面的图片保存到文件夹 并且保存到数据库中关联起来 在上传时判断是否为zip格式的文件 @RequestMappin ...

  2. C# 将服务器文件批量压缩打包下载至本地两种方法(压缩包缓存到服务器下载、压缩包缓存到内存下载)

    1.将服务器文件打包下载至本地(压缩包缓存到服务器下载) (1)文件批量压缩成压缩包并缓存到服务器(公共方法) using ICSharpCode.SharpZipLib.Checksums; usi ...

  3. 使用Java生成的ZIP压缩包解压时出现不可预料的压缩文件末端的解决方案

    使用Java生成的ZIP压缩包解压时出现不可预料的压缩文件末端的解决方案 问题描述: 如下图所示,在解压Java程序生成的ZIP压缩包时出现不可预料的压缩文件末端, 问题分袖: 出现上面的情况,大概有 ...

  4. jdk下没有java源码_openJDK之如何下载各个版本的openJDK源码

    如果我们需要阅读openJDK的源码,那么需要下载,那么该去哪下载呢? 现在JDK已经发展到版本10了,11已经处于计划中,如果需要特定版本的openJDK,它们的下载链接在哪呢? 1.openJDK ...

  5. java演练 循环嵌套 菱形图案的打印 四个阶段完成输出

    java演练 循环嵌套 菱形图案的打印 阶段一,视频 https://www.ixigua.com/6870331861256634894/ 阶段一,数据分析 阶段二,视频 http://mp.tou ...

  6. Java百度网盘创建链接,java获取百度网盘真实下载链接的方法

    本文实例讲述了java获取百度网盘真实下载链接的方法.分享给大家供大家参考.具体如下: 目前还存在一个问题,同一ip在获取3次以后会出现验证码,会获取失败,感兴趣的朋友对此可以加以完善. 返回的Lis ...

  7. 【JAVA资料免费下载】158个JAVA免豆精品资料汇总——下载目录(转载)

    [JAVA资料免费下载]158个JAVA免豆精品资料汇总--下载目录(转载) 应广大网友要求,最近小弟整理了一批免积分下载的Java优质资料,因资料众多,一一将资料上传上来需要时间,先将下载目录分享给 ...

  8. java技术分享主题_Java开发入门:适合新手练手的Java项目(附源码下载)

    Java作为一门古老的语言,已有20年左右的历史,这在发展日新月异的技术圈可以说是一个神话.虽然不少人曾抱怨Java语言就像老太太的裹脚布,又臭又长,有时写了500行都不能表达程序员的意图. 但从市场 ...

  9. java解析多层嵌套json字符串

    java解析多层嵌套json字符串 java分别解析下面两个json字符串 package jansonDemo;import com.alibaba.fastjson.JSON; import co ...

  10. java循环的嵌套执行

    java循环的嵌套执行 /*** 循环的嵌套执行*/ public class Test14 {public static void main(String[] args) {/*** 外层循环执行一 ...

最新文章

  1. 输出可爱的”杨辉三角”
  2. ascii码01100001_ASCII编码和Unicode编码
  3. java hh mm ss_【Java基础】比较时间大小(以HH:mm:ss格式为例)
  4. 集成测试用例_如何评估测试用例的有效性?
  5. centos如何编译安装mysql_CentOS中如何编译安装MySQL数据库教程
  6. asp.net Viewstate 优化
  7. 28岁的李佳琪落户上海了
  8. mysql 增加一列 伦理名_MySQL错误提示mysql Statement violates GTID consistency
  9. 利用并查集+贪心解决 Hdu1232
  10. jquery中如何获得时间
  11. 微信小程序引入阿里巴巴icon步骤及报错解决
  12. C#使用DirectoryEntry类操作Windows帐户
  13. 使用matlab时括号附近出现红色波浪线“使用的MATLAB语法可能无效”提示
  14. HTML编辑器-HTML网页表单可视化在线编辑器插件大全
  15. android自带下拉阻尼动画,Android 阻尼回弹效果简单实现(类似iOS)
  16. 关于特修斯之船(转自知乎)
  17. 转文:华为鸿蒙操作系统全景解构
  18. 微信小程序开发手记之七:一个小程序上线后的总结(上)
  19. JDBC 第一章 JDBC概述
  20. RT-Thread进阶之低功耗PM组件应用笔记

热门文章

  1. 【笔记】Telink BDT EVK烧录时错误
  2. Go语言 常用日志记录方法
  3. 计算机网络之广域网基础以及华为eNSP实验配置
  4. angular对象简单介绍
  5. 装完金蝶电脑无限重启_电脑一直自动重启的原因与解决方法
  6. 程序员年薪40万被国企同学怒怼:没啥贡献,工资这么高,凭什么?
  7. bzoj-1488 图的同构
  8. 基于Proteus无实物STM32入门自学教程(三)--静态数码管
  9. pandas的重复值的处理
  10. 【微信小程序】针对测试号获取openid报错40125错误的解决方案