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 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]); } }