使用的jar包:zip4j_1.3.2.jar
基本功能:
针对ZIP压缩文件创建、添加、分卷、更新和移除文件
(读写有密码保护的Zip文件)
(支持AES 128/256算法加密)
(支持标准Zip算法加密)
(支持zip64格式)
(支持Store(仅打包,默认不压缩,不过可以手动设置大小)和Deflate压缩方法
(针对分块zip文件创建和抽出文件)
(支持编码)
(进度监控)
压缩方式(3种):
static final int COMP_STORE = 0;(仅打包,不压缩) (对应好压的存储)
static final int COMP_DEFLATE = 8;(默认) (对应好压的标准)
static final int COMP_AES_ENC = 99;

压缩级别有5种:(默认0不压缩)级别跟好压软件是对应的;
static final int DEFLATE_LEVEL_FASTEST = 1;
static final int DEFLATE_LEVEL_FAST = 3;
static final int DEFLATE_LEVEL_NORMAL = 5;
static final int DEFLATE_LEVEL_MAXIMUM = 7;
static final int DEFLATE_LEVEL_ULTRA = 9;
加密方式:
static final int ENC_NO_ENCRYPTION = -1;(默认,没有加密方法,如果采用此字段,会报错”没有提供加密算法”)
static final int ENC_METHOD_STANDARD = 0;
static final int ENC_METHOD_AES = 99;
AES Key Strength:
(默认-1,也就是ENC_NO_ENCRYPTION)
static final int AES_STRENGTH_128 = 0x01;
static final int AES_STRENGTH_192 = 0x02;
static final int AES_STRENGTH_256 = 0x03;

从构造方法可以默认情况:
compressionMethod = Zip4jConstants.COMP_DEFLATE;
encryptFiles = false;//不设密码
readHiddenFiles = true;//可见
encryptionMethod = Zip4jConstants.ENC_NO_ENCRYPTION;//加密方式不加密
aesKeyStrength = -1;//
includeRootFolder = true;//
timeZone = TimeZone.getDefault();//

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
* 情景教学压缩操作类 */
public class CompressHandler extends Thread { private Logger logger = Logger.getLogger(CompressHandler.class); /**
* 存储目录名和对应目录下的文件地址 */
private Map<String, List<ResourceInfo>> resourceMap; /**

* 压缩类中的配置文件 */
private String configJson; /**

* 配置文件map key为压缩包中的文件名,value为文件内容 */
Map<String, String> configJsonMap; /**

* 回调接口 */
private ZipOperate zipOperate; /**

* 加密标志 */
private boolean encrypt = false; /**

* 线程名称 */
private String threadName = Thread.currentThread().getName(); /**

* 取消标志 */
private boolean cancelFlag; public CompressHandler() {
} public CompressHandler(Map<String, List<ResourceInfo>> resourceMap, Map<String, String> configJsonMap, ZipOperate zipOperate) { this(resourceMap, configJsonMap, zipOperate, false);
} public CompressHandler(Map<String, List<ResourceInfo>> resourceMap, Map<String, String> configJsonMap, ZipOperate zipOperate, boolean encrypt) { this.resourceMap = resourceMap; this.configJsonMap = configJsonMap; this.zipOperate = zipOperate; this.encrypt = encrypt;
} public CompressHandler(Map<String, List<ResourceInfo>> resourceMap, String configJson, ZipOperate zipOperate) { this(resourceMap, configJson, zipOperate, false);
} public CompressHandler(Map<String, List<ResourceInfo>> resourceMap, String configJson, ZipOperate zipOperate, boolean encrypt) { this.resourceMap = resourceMap; this.configJson = configJson; this.zipOperate = zipOperate; this.encrypt = encrypt;
}
@Override public void run() { if (zipOperate != null) {

zipOperate.beforeCompress();

}
String fileName = UUID.randomUUID().toString().replace("-", "").concat(".zip");
String tempDir = SuperdiamondConfig.getConfig(SuperdiamondConfig.SYSTEM_TMMP_FILE_PATH);
File tempDirFile = new File(tempDir); if (!tempDirFile.exists()) {

tempDirFile.mkdir();

}
String filePath = tempDir.concat("/").concat(fileName); //存储生成本地压缩包的文件
List<File> encryptFileList = new ArrayList<>(); try {

ZipFile zipFile = new ZipFile(filePath);
logger.info("线程" + threadName + " 开始压缩,压缩的文件名为:" + fileName); long startTime = System.currentTimeMillis();
logger.info("线程" + threadName + " 开始时间为:" + startTime);
ZipParameters parameters = new ZipParameters(); //设置压缩方式和压缩级别
parameters.setCompressionMethod(Zip4jConstants.COMP_DEFLATE);
parameters.setCompressionLevel(Zip4jConstants.DEFLATE_LEVEL_NORMAL); //当开启压缩包密码加密时
boolean dirEncrypt = false; if (encrypt || Boolean.parseBoolean(SuperdiamondConfig.getConfig(SuperdiamondConfig.ENABLE_ENCRYPT_ZIP))) {
logger.info("线程" + threadName + " 该压缩包需要加密");
addEncryptParameters(parameters);
dirEncrypt = true;
} for (String dir : resourceMap.keySet()) {
logger.info("线程" + threadName + " 添加目录:" + dir);
List<ResourceInfo> resourceInfoList = resourceMap.get(dir); for (ResourceInfo resourceInfo : resourceInfoList) {
String resourceFileName = resourceInfo.getFileName();
logger.info("线程" + threadName + " 添加文件:" + resourceFileName); /**
* 20180921判断目录名是否为空字符串 true不创建目录 by lizhang10 */
if(StringUtils.isNotEmpty(dir)){
parameters.setFileNameInZip(dir + "/" + resourceFileName);
}else{
parameters.setFileNameInZip(resourceFileName);
}
parameters.setSourceExternalStream(true);
InputStream inputStream = resourceInfo.getInputStream(); if (inputStream == null) { //获取文件流
String fileUrl = resourceInfo.getFileUrl(); long startTime1 = System.currentTimeMillis();
logger.info("线程" + threadName + " 开始获取文件流,地址:" + fileUrl + " 开始时间:" + startTime1);
inputStream = getInputStream(fileUrl); long endTime1 = System.currentTimeMillis();
logger.info("线程" + threadName + " 结束获取文件流,地址:" + fileUrl + " 结束时间:" + endTime1 + " 耗时毫秒: " + (endTime1 - startTime1));
} //当压缩包没有加密时,则从文件属性中取是否进行加密
if(!dirEncrypt && resourceInfo.isEncrypt()){ //如果是zip的话,则对文件进行解压,然后再加密
if(resourceFileName.endsWith(".zip")){ long saveStartTime = System.currentTimeMillis(); //网络文件路径
String sourceFileName = tempDir.concat("/").concat(UUID.randomUUID().toString().concat(".zip"));
logger.info("线程" + threadName + " 该文件["+resourceFileName+"]是zip且需要加密,开始存到本地,路径为:"+sourceFileName+"开始时间:" + saveStartTime); //加密文件路径
String encryptFileName = tempDir.concat("/").concat(UUID.randomUUID().toString().concat(".zip"));
File file = new File(sourceFileName);
FileOutputStream outputStream = new FileOutputStream(file); byte[] buffer = new byte[8*1024]; int len = 0; while ((len = inputStream.read(buffer)) != -1){
outputStream.write(buffer,0,len);
}
outputStream.close();
inputStream.close(); long saveEndTime = System.currentTimeMillis();
logger.info("线程" + threadName + " 该文件是zip,存到本地完成,结束时间:" + saveEndTime + " 耗时:"+(saveEndTime - saveStartTime)); long extractStartTime = System.currentTimeMillis();
logger.info("线程" + threadName + " ,开始进行解压加密,开始时间为:" + extractStartTime);
ZipFile sourceZipFile = new ZipFile(file);
String extractDir = tempDir.concat("/").concat(UUID.randomUUID().toString());
sourceZipFile.extractAll(extractDir); long extractEndTime = System.currentTimeMillis();
ZipFile encryptZipFile = new ZipFile(encryptFileName);
ZipParameters parameters2 = new ZipParameters(); //设置压缩方式和压缩级别
parameters2.setCompressionMethod(Zip4jConstants.COMP_DEFLATE);
parameters2.setCompressionLevel(Zip4jConstants.DEFLATE_LEVEL_NORMAL);
addEncryptParameters(parameters2); //添加获取文件的文件和目录
File[] fileArray = new File(extractDir).listFiles(); for (File file1 : fileArray) { if(file1.isDirectory()){
encryptZipFile.addFolder(file1,parameters2);
} else {
encryptZipFile.addFile(file1,parameters2);
}
} if(!StringUtils.isEmpty(resourceInfo.getConfigJson())){
parameters2.setFileNameInZip("config.json");
parameters2.setSourceExternalStream(true);
encryptZipFile.addStream(new ByteArrayInputStream(resourceInfo.getConfigJson().getBytes("utf8")),parameters2);
}
logger.info("线程" + threadName + " ,完成解压加密,结束时间为:" + extractEndTime + " 耗时: " + (extractEndTime-extractStartTime)); //删除文件
sourceZipFile.getFile().delete(); //删除目录下的文件
deleteFolder(new File(extractDir));
File encryptFile = encryptZipFile.getFile();
inputStream = new FileInputStream(encryptFile);
encryptFileList.add(encryptFile);
}
} //获取需要打包的文件流
zipFile.addStream(inputStream, parameters);
inputStream.close();
}
}
parameters.setSourceExternalStream(true); //如果configJsonMap不为空,且length不为0,则遍历加入到压缩包中
if (configJsonMap != null && configJsonMap.size() > 0) { for (String resourceName : configJsonMap.keySet()) {
logger.info("线程" + threadName + " 添加配置文件" + resourceName);
parameters.setFileNameInZip(resourceName);
String value = configJsonMap.get(resourceName);
zipFile.addStream(new ByteArrayInputStream(value.getBytes("utf8")), parameters);
}
} if (!StringUtils.isEmpty(configJson)) {
logger.info("线程" + threadName + " 添加文件config.json");
parameters.setFileNameInZip("config.json");
zipFile.addStream(new ByteArrayInputStream(configJson.getBytes("utf8")), parameters);
}
logger.info("线程" + threadName + " 压缩文件" + fileName + "完成"); long endTime = System.currentTimeMillis();
logger.info("线程" + threadName + " 结束时间为:" + endTime + " 耗时毫秒:" + (endTime - startTime)); long startTime2 = System.currentTimeMillis();
logger.info("线程" + threadName + " 开始将压缩包上传到文件服务.......开始时间:" + startTime2);
FileInfo fileInfo = new CystrageUtil().uploadToRemoteServer(fileName, filePath, null); long endTime2 = System.currentTimeMillis();
logger.info("线程" + threadName + " 上传完成.......结束时间:" + endTime2 + "耗时毫秒: " + (endTime2 - startTime2)); if (cancelFlag){ throw new InterruptedException("线程" + threadName + " 取消压缩");
} //如果传入了后续操作接口,则将文件服务返回的类传入
if (zipOperate != null) {
zipOperate.afterCompress(fileInfo, zipFile);
zipFile.getFile().delete();
}

} catch (Exception e) {

logger.error("线程" + threadName + " 文件压缩出错...........文件内容:" + configJson, e); if (zipOperate != null) {
zipOperate.errorCompress();
} //删除对应压缩包
new File(filePath).delete();

} finally { try { //关流

inputStream.close();
} catch (IOException e) {
inputStream = null;
} //删除本地生成的压缩文件 //存储生成本地压缩包的文件
for (File file : encryptFileList) {
file.delete();
}

}
} /**

* 删除文件夹下的所有文件

* @param sourceDir */
private void deleteFolder(File sourceDir) { if(sourceDir.isDirectory()){

File[] files = sourceDir.listFiles(); for (File file : files) {
deleteFolder(file);
}

} else {

sourceDir.delete();

}
sourceDir.delete();
} private void addEncryptParameters(ZipParameters parameters) {
String password = SuperdiamondConfig.getConfig(SuperdiamondConfig.ZIP_COMPRESS_PASSWORD);
parameters.setEncryptFiles(true);
parameters.setEncryptionMethod(Zip4jConstants.ENC_METHOD_AES);
parameters.setAesKeyStrength(Zip4jConstants.AES_STRENGTH_256);
parameters.setPassword(password.toCharArray());
} /**

* 获取输入流

*

* @param fileUrl

* @return
*/
InputStream inputStream; private InputStream getInputStream(String fileUrl) throws Exception { if(cancelFlag){ throw new InterruptedException("线程" + threadName + " 取消压缩");
} int retry = 1; while (retry <= 3) { try { int index = fileUrl.lastIndexOf("/");

String prefix = fileUrl.substring(0, index + 1);
String fileName = fileUrl.substring(index + 1);
URL url = new URL(prefix + URLEncoder.encode(fileName, "utf8"));
URLConnection connection = url.openConnection();
connection.setDoInput(true);
inputStream = connection.getInputStream(); return inputStream;
} catch (Exception e) { if (retry == 1) {
logger.error("线程" + threadName + " 获取文件出错,文件地址:" + fileUrl, e);
}
logger.error("开始重试第" + retry + "次"); //由于测试环境服务器承载能力比较差,当获取失败后,睡眠一段时间再重试
if(Boolean.parseBoolean(SuperdiamondConfig.getConfig(SuperdiamondConfig.SYSTEM_TEST_ENVIRONMENT))){
Thread.currentThread().sleep(Long.parseLong(SuperdiamondConfig.getConfig(SuperdiamondConfig.SYSTEM_SLEEP_TIME)));
} if (retry == 3) { throw new Exception(e);
}
retry++;
}

} return null;
} public void setCancelFlag(Boolean cancelFlag){ this.cancelFlag = cancelFlag;
}
@Override public void interrupt() { if (inputStream != null) { try {

inputStream.close();
} catch (IOException e) {
inputStream = null;
logger.info("线程" + threadName + " 关闭io流失败");
}

} super.interrupt();
} public static class ResourceInfo { /**

* 文件名称 */
private String fileName; /**
* 文件地址 */
private String fileUrl; /**
* 输入流 */
private InputStream inputStream; /**
* 是否要为当前文件添加config,json */
private String configJson; /**
* 改文件是否加密 */
private boolean encrypt; public InputStream getInputStream() { return inputStream;
} public void setInputStream(InputStream inputStream) { this.inputStream = inputStream;
} public String getFileName() { return fileName;
} public void setFileName(String fileName) { this.fileName = fileName;
} public String getFileUrl() { return fileUrl;
} public void setFileUrl(String fileUrl) { this.fileUrl = fileUrl;
} public boolean isEncrypt() { return encrypt;
} public void setEncrypt(boolean encrypt) { this.encrypt = encrypt;
} public String getConfigJson() { return configJson;
} public void setConfigJson(String configJson) { this.configJson = configJson;
}
}
}