package com.ard.inspection.utils;
|
|
import org.apache.commons.compress.archivers.zip.ZipArchiveEntry;
|
import org.apache.commons.compress.archivers.zip.ZipFile;
|
import org.slf4j.Logger;
|
import org.slf4j.LoggerFactory;
|
import org.springframework.beans.factory.annotation.Value;
|
import org.springframework.stereotype.Component;
|
|
import java.io.*;
|
import java.nio.file.Files;
|
import java.nio.file.Path;
|
import java.nio.file.Paths;
|
import java.util.Comparator;
|
import java.util.Enumeration;
|
|
/**
|
* ZIP文件解压工具类
|
*/
|
@Component
|
public class ZipFileUtils {
|
|
private static final Logger log = LoggerFactory.getLogger(ZipFileUtils.class);
|
|
@Value(value = "${inspection.chunk.zipPath}")
|
private String zipPath;
|
|
/**
|
* 解压ZIP文件到指定目录
|
* @param zipFilePath 压缩包路径
|
* @param overwrite 是否覆盖已存在文件
|
* @throws IOException 解压异常
|
*/
|
public void unzip(String zipFilePath, boolean overwrite) throws IOException {
|
// 校验压缩包是否存在
|
File zipFile = new File(zipFilePath);
|
if (!zipFile.exists()) {
|
throw new FileNotFoundException("压缩包不存在:" + zipFilePath);
|
}
|
|
// 创建目标目录
|
Path targetDir = Paths.get(zipPath);
|
if (!Files.exists(targetDir)) {
|
Files.createDirectories(targetDir);
|
}
|
|
// 使用Apache Commons Compress处理大ZIP文件
|
try (ZipFile zf = new ZipFile(zipFile)) {
|
Enumeration<ZipArchiveEntry> entries = zf.getEntries();
|
while (entries.hasMoreElements()) {
|
ZipArchiveEntry entry = entries.nextElement();
|
String entryName = entry.getName();
|
// 拼接解压后的文件路径
|
Path entryPath = targetDir.resolve(entryName);
|
|
// 跳过已存在且不覆盖的文件
|
if (Files.exists(entryPath) && !overwrite) {
|
log.warn("文件已存在,跳过解压:{}", entryPath);
|
continue;
|
}
|
|
// 如果是目录,创建目录
|
if (entry.isDirectory()) {
|
if (!Files.exists(entryPath)) {
|
Files.createDirectories(entryPath);
|
}
|
continue;
|
}
|
|
// 创建父目录(防止文件在子目录下)
|
Path parentDir = entryPath.getParent();
|
if (!Files.exists(parentDir)) {
|
Files.createDirectories(parentDir);
|
}
|
|
// 流式复制文件(避免内存溢出)
|
try (InputStream in = zf.getInputStream(entry);
|
OutputStream out = Files.newOutputStream(entryPath)) {
|
byte[] buffer = new byte[8192]; // 8K缓冲区
|
int len;
|
while ((len = in.read(buffer)) != -1) {
|
out.write(buffer, 0, len);
|
}
|
log.info("解压文件完成:{}", entryPath);
|
}
|
}
|
} catch (Exception e) {
|
log.error("解压文件失败:{}", zipFilePath, e);
|
throw new IOException("解压失败:" + e.getMessage(), e);
|
}
|
}
|
|
/**
|
* 解压ZIP文件到指定目录
|
* @param pathStr 删除文件夹路径
|
*/
|
public boolean deleteZipFile(String pathStr) {
|
if (pathStr == null || pathStr.isEmpty()) {
|
return false;
|
}
|
Path path = Paths.get(pathStr);
|
if (!Files.exists(path)) {
|
// 路径不存在,视为删除成功
|
return true;
|
}
|
try {
|
// 遍历并反向排序,确保先删除子文件/子目录,再删除父目录
|
Files.walk(path)
|
.sorted(Comparator.reverseOrder())
|
.forEach(p -> {
|
try {
|
Files.deleteIfExists(p);
|
} catch (IOException e) {
|
throw new RuntimeException("删除失败: " + p, e);
|
}
|
});
|
return true;
|
} catch (IOException e) {
|
e.printStackTrace();
|
return false;
|
}
|
}
|
|
/**
|
* 根据文件大小格式化
|
* @param size 文件大小
|
*/
|
public static String formatFileSize(long size) {
|
if (size <= 0) return "0 B";
|
final String[] units = new String[]{"B", "KB", "MB", "GB", "TB"};
|
int digitGroups = (int) (Math.log10(size) / Math.log10(1024));
|
return String.format("%.2f %s", size / Math.pow(1024, digitGroups), units[digitGroups]);
|
}
|
|
}
|