1.背景:
实际应用中,批量导出exel的功能,用户为了方便归类整理,要求导出一个压缩包,然后压缩包里再按某种规则进行压缩打包excel。最终导出到本地环境的文件是一个压缩包套压缩包的形式。
2.原理:
里层一个压缩流,外层一个总的压缩流,用两个压缩流导出。
3.实现:
// 外层压缩流
ZipArchiveOutputStream zos=new ZipArchiveOutputStream(new File(zipName));
zos.setEncoding("UTF8");
ZipEncoding zipEncoding = ZipEncodingHelper.getZipEncoding("UTF8");
InputStream input = null;
BufferedInputStream bis = new BufferedInputStream(new FileInputStream(zipName1));
for(){
//业务代码
......
ZipArchiveOutputStream zos1 = new ZipArchiveOutputStream(new File(zipName2));
zos1.setEncoding("UTF8");
ZipEncoding zipEncoding1 = ZipEncodingHelper.getZipEncoding("UTF8");
BASE64Decoder decoder = new BASE64Decoder();
for(){
//业务代码
......
// excelContent为要导出的String流
byte[] b=decoder.decodeBuffer(excelContent);
InputStream in = new ByteArrayInputStream(b);
// 创建输入流读取文件
BufferedInputStream bis1 = new BufferedInputStream(in);
// 将excel文件写入zip内,即将文件进行打包
ZipArchiveEntry zipEntry = new ZipArchiveEntry(reportName + ".xlsx");
ByteBuffer byteBuffer = zipEncoding1.encode(reportName + ".xlsx");
// 从给定的文件名称和字节数组组装unicode路径名称
UnicodePathExtraField unicodePathExtraField = new UnicodePathExtraField(reportName + ".xlsx", byteBuffer.array(),
byteBuffer.arrayOffset(), byteBuffer.limit() - byteBuffer.position());
zipEntry.addExtraField(unicodePathExtraField);
zos1.putArchiveEntry(zipEntry);
// 写入文件的方法,同上
int size = 0;
// 设置读取数据缓存大小
byte[] buffer = new byte[1024];
while ((size = bis1.read(buffer)) > 0) {
zos1.write(buffer, 0, size);
}
zos1.closeArchiveEntry();
bis1.close();
}
zos1.close();
// 向总的压缩包里写入非结构化的压缩包
input = new FileInputStream(fileBran);
ZipArchiveEntry zipEntry = new ZipArchiveEntry(fileName);
ByteBuffer byteBuffer = zipEncoding.encode(fileName);
// 从给定的文件名称和字节数组组装unicode路径名称
UnicodePathExtraField unicodePathExtraField = new UnicodePathExtraField(fileName,
byteBuffer.array(), byteBuffer.arrayOffset(), byteBuffer.limit() - byteBuffer.position());
zipEntry.addExtraField(unicodePathExtraField);
zos.putArchiveEntry(zipEntry);
int temp = 0;
while ((temp = input.read()) != -1) {
zos.write(temp);
}
zos.flush();
zos.closeArchiveEntry();
}
input.close();
zos.flush();
zos.close();
// 下载的时候兼容IE浏览器
String userAgent = request.getHeader("user-agent").toLowerCase();
// win10 ie edge 浏览器 和其他系统的ie
if (userAgent.contains("msie") || userAgent.contains("like gecko")) {
try {
zipName = URLEncoder.encode(zipName, "utf-8");
} catch (UnsupportedEncodingException e) {
logger.error("win10 ie edge 浏览器 和其他系统的ie-生成压缩文件名出错:", e);
}
} else {
// 其他浏览器
zipName = new String((zipName).getBytes(StandardCharsets.UTF_8), StandardCharsets.ISO_8859_1);
}
response.setContentType("application/octet-stream; charset=utf-8");
response.setHeader("Content-Disposition", "attachment; filename=" + zipName);
// 创建页面返回方式为输出流,会自动弹出下载框
OutputStream out = response.getOutputStream();
// 将打包后的文件写到客户端,输出的方法同上,使用缓冲流输出
bis = new BufferedInputStream(new FileInputStream(zipName));
byte[] zbuff = new byte[bis.available()];
bis.read(zbuff);
bis.close();
// 输出数据文件
out.write(zbuff);
// 释放缓存
out.flush();
// 关闭输出流
out.close();
以上就是导出压缩包套压缩包文件的大致流程代码。