上传压缩包、解析压缩包(zip)
最近工作中遇到了上传压缩包的需求,把这个记录下来。
主要内容:
1:上传zip压缩包
2:解压zip压缩包到指定路劲、解压后文件夹名乱码问题
3:支持重复上传(只保留最新的压缩包,删除老的压缩包、解压后的文件夹及文件夹内所有文件)
前置工作
添加pom依赖
<!--解压zip压缩-->
<dependency>
<groupId>net.lingala.zip4j</groupId>
<artifactId>zip4j</artifactId>
<version>1.3.2</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-test</artifactId>
</dependency>
<dependency>
<groupId>org.apache.httpcomponents</groupId>
<artifactId>httpclient</artifactId>
</dependency>
压缩包和文件夹目录层次:压缩包名称和文件夹名称一致。也可以不一样,代码里folderName是文件夹名称
1:上传和解压
将请求中的压缩包,存到某个路劲。这个功能很简单。
MultipartFile提供了 transferTo方法。可以直接将文件复制到指定路劲(也可以顺便换个名)
//解压路劲 这里改成自己的路劲
private String uploadUrl = E:/1.IDEA/Workspace/helloFile/;
@PostMapping("uploadPackage")
public BaseResponse uploadPackage(@RequestPart(name = "file") MultipartFile file) throws Exception {
String packageName = file.getOriginalFilename();
String folderName = packageName.substring(0, packageName.length() - 4);
//检查是否已存在
log.debug("检查压缩包是否存在");
File oldFile = new File(uploadUrl + packageName);
if (oldFile != null) {
//实现幂等
oldFile.delete();
deleteAllFile(uploadUrl + folderName);
}
//复制压缩包
log.debug("复制压缩包到指定路劲");
file.transferTo(new File(uploadUrl + packageName));
log.debug("开始解压...");
if (file.getOriginalFilename().indexOf(".zip") > 0) {
unPackZip(packageName, uploadUrl);
}
//解压
log.info("上传并解压成功");
return new BaseResponse(Msg.SUCCESS);
}
实现幂等:deleteAllFile()
只保留最新的压缩包和解压文件夹
ps:自带的delete()方法只能删除当前文件(如果是文件夹的话,不能删除文件夹内的文件,导致最外层文件夹也不能删除)
/**
* 递归实现 删除文件夹下所有目录及文件
**/
public boolean deleteAllFile(String path) {
File file = new File(path);
if (!file.exists()) {
return false;
}
if (file.isFile()) {
return file.delete();
}
File[] files = file.listFiles();
for (File f : files) {
if (f.isFile()) {
if (!f.delete()) {
return false;
}
} else {
if (!this.deleteAllFile(f.getAbsolutePath())) {
return false;
}
}
}
return file.delete();
}
解压模块: unPackZip()
//解压zip包,解决文件夹乱码问题
public void unPackZip(String fileName, String destPath) throws Exception {
ZipFile zipFile = new ZipFile(destPath + fileName);
//getEncoding()解决字符集乱码
zipFile.setFileNameCharset(getEncoding(destPath + fileName));
zipFile.extractAll(destPath);
}
//getEncoding()解决字符集乱码
private static String getEncoding(String path) throws Exception {
String encoding = "GBK";
ZipFile zipFile = new ZipFile(path);
zipFile.setFileNameCharset(encoding);
List<FileHeader> list = zipFile.getFileHeaders();
for (int i = 0; i < list.size(); i++) {
FileHeader fileHeader = list.get(i);
String fileName = fileHeader.getFileName();
if (isMessyCode(fileName)) {
encoding = "UTF-8";
break;
}
}
return encoding;
}
//判断字符集
private static boolean isMessyCode(String str) {
for (int i = 0; i < str.length(); i++) {
char c = str.charAt(i);
// 当从Unicode编码向某个字符集转换时,如果在该字符集中没有对应的编码,则得到0x3f(即问号字符?)
// 从其他字符集向Unicode编码转换时,如果这个二进制数在该字符集中没有标识任何的字符,则得到的结果是0xfffd
if ((int) c == 0xfffd) {
// 存在乱码
return true;
}
}
return false;
}
2:看下效果
postman请求参数:
注意选择参数类型为File
执行结果: