使用zip4j批量下载文件,并压缩打包,支持加密
直接获取输入流,不用产生本地临时文件再打包
依赖代码net.lingala.zip4j zip4j1.3.2
public void download(HttpServletResponse response, StoreVO vo) {
IStoreClient client = storeClient.getClient();
client.open(store -> {
ZipOutputStream zos = null;
OutputStream out = null;
try {
out = response.getOutputStream();
zos = new ZipOutputStream(out);
zipEncryptionFile(store, zos, vo);
} finally {
if (zos != null) {
zos.finish();
zos.close();
}
}
});
}
private void zipEncryptionFile(IStoreHandler store, ZipOutputStream zos, StoreVO vo) throws ZipException, IOException {
ZipParameters para = getZipParameters(vo);
// fileToZip(store, zos, vo.getCurDirName(), vo.getDirList(), para);
fileToZip(store, zos, vo.getCurDirName(), vo.getFileList(), para);
}
private ZipParameters getZipParameters(StoreVO vo) {
ZipParameters para = new ZipParameters();
// 压缩方式
para.setCompressionMethod(Zip4jConstants.COMP_DEFLATE);
para.setSourceExternalStream(true);
// 压缩级别
para.setCompressionLevel(Zip4jConstants.DEFLATE_LEVEL_NORMAL);
if (vo.getEncrypt()) {
para.setEncryptFiles(true);
para.setEncryptionMethod(Zip4jConstants.ENC_METHOD_AES);
para.setAesKeyStrength(Zip4jConstants.AES_STRENGTH_256);
para.setPassword(vo.getPassword());
}
return para;
}
private static void fileToZip(IStoreHandler store, ZipOutputStream zos, String dir, List fileList, ZipParameters para) {
fileList.forEach(fileName -> {
try {
InputStream in = store.getInputStream(dir, fileName);
para.setFileNameInZip(fileName);
zos.putNextEntry(new File(fileName), para);
byte[] buffer = new byte[1024];
int len;
while ((len = in.read(buffer)) > 0) {
zos.write(buffer, 0, len);
}
zos.closeEntry();
in.close();
} catch (Exception e) {
throw new RuntimeException(e);
}
});
}
StoreVO
@Data
@Builder
@AllArgsConstructor
@NoArgsConstructor
public class StoreVO {
private Long userId;
private String curDirName;
private java.util.List fileList;
private Boolean compress;
private Boolean encrypt;
private String password;
private String zipName;
}
遇到过的问题
1.打开时出现“不可预料的压缩文件末端”
因为代码涉及多个输入输出流,开始使用try-with-resource的方式关闭流,但是发现这样关闭顺序不好控制,所以还是要收到控制
关键点是在使用完ZipOutputStream以后添加zos.finish();就好了
2.“这个压缩文件格式未知或者数据已经被损坏原因是要设置ZipParameters的fileNameInZip属性,我开始以为是压缩文件名的意思,下下来打开里面都是同名的压缩文件。。
酱紫写:para.setFileNameInZip(“压缩包里的文件名称”)



