package com.chinaunicom.asset.common.utils.compress; import lombok.extern.slf4j.Slf4j; import org.apache.commons.compress.archivers.ArchiveEntry; import org.apache.commons.io.FilenameUtils; import org.apache.commons.io.IOUtils; import org.springframework.util.FileSystemUtils; import java.io.Closeable; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.nio.file.Files; import java.nio.file.Path; @Slf4j public abstract class AbstractArchive implements Closeable { private static final int THRESHOLD_ENTRIES = 10_000; private static final int THRESHOLD_SIZE = 1_000_000_000; // 1 GB private final Path archive; protected AbstractArchive(Path archive) { this.archive = archive; } protected Path getArchive() { return archive; } protected abstract ArchiveEntry nextEntry() throws IOException; protected abstract InputStream getInputStream() throws IOException; protected abstract boolean skipEntry(); // 不解压macOS的meta data文件 protected static boolean isMacOSMetaData(String entryName) { if (entryName.startsWith("__MACOSX/")) { return true; } return entryName.endsWith("/.DS_Store") || entryName.equals(".DS_Store"); } public void decompress(Path decompressedPath) throws IOException { ArchiveEntry entry; int totalSize = 0; int archiveEntries = 0; while ((entry = nextEntry()) != null) { InputStream in = getInputStream(); if (skipEntry()) { continue; } Path entryDest = decompressedPath.resolve(entry.getName()); if (entry.isDirectory()) { Files.createDirectories(entryDest); } else { writeToDest(in, entryDest); validateTotal(archiveEntries++, decompressedPath); totalSize += entry.getSize(); validateTotalSize(totalSize, decompressedPath); } } } public static AbstractArchive newArchive(Path archivePath) throws IOException { String extension = FilenameUtils.getExtension(archivePath.getFileName().toString()); switch (extension.toLowerCase()) { case "zip": return new ZipArchive(archivePath); case "7z": return new SevenZArchive(archivePath); default: throw new IllegalArgumentException("Unsupported Archive Type:" + extension); } } private static void writeToDest(InputStream in, Path entryDest) throws IOException { Files.createDirectories(entryDest.getParent()); try (OutputStream out = Files.newOutputStream(entryDest)) { IOUtils.copy(in, out); } } private static void validateTotalSize(int totalSize, Path decompressedPath) { if (totalSize > THRESHOLD_SIZE) { log.error("文件过大:{},终止解压", totalSize); cleanOnFailed(decompressedPath); throw new IllegalArgumentException("压缩文件过大,解压失败"); } } private static void validateTotal(int archiveEntries, Path decompressedPath) { if (archiveEntries > THRESHOLD_ENTRIES) { log.error("文件数量过多,终止解压"); cleanOnFailed(decompressedPath); throw new IllegalArgumentException("压缩文件内文件过多,解压失败"); } } private static void cleanOnFailed(Path targetPath) { try { FileSystemUtils.deleteRecursively(targetPath); } catch (IOException e) { log.error("清理文件失败:{}", e.getMessage(), e); } } }
package com.chinaunicom.asset.common.utils.compress; import lombok.extern.slf4j.Slf4j; import org.apache.commons.compress.archivers.ArchiveEntry; import org.apache.commons.compress.archivers.ArchiveInputStream; import org.apache.commons.compress.archivers.zip.ZipArchiveInputStream; import java.io.IOException; import java.io.InputStream; import java.nio.file.Files; import java.nio.file.Path; @Slf4j public class ZipArchive extends AbstractArchive { private final ArchiveInputStream inputStream; private ArchiveEntry currentEntry; public ZipArchive(Path archivePath) throws IOException { super(archivePath); this.inputStream = new ZipArchiveInputStream(Files.newInputStream(getArchive())); } @Override protected ArchiveEntry nextEntry() throws IOException { currentEntry = inputStream.getNextEntry(); return currentEntry; } @Override protected InputStream getInputStream() { return inputStream; } @Override protected boolean skipEntry() { // 跳过无法读取的文件 if (!inputStream.canReadEntryData(currentEntry)) { log.warn("压缩包内存在无法读取的文件"); return true; } return isMacOSMetaData(currentEntry.getName()); } @Override public void close() throws IOException { this.inputStream.close(); } }
package com.chinaunicom.asset.common.utils.compress; import org.apache.commons.compress.archivers.ArchiveEntry; import org.apache.commons.compress.archivers.sevenz.SevenZArchiveEntry; import org.apache.commons.compress.archivers.sevenz.SevenZFile; import java.io.IOException; import java.io.InputStream; import java.nio.file.Files; import java.nio.file.Path; public class SevenZArchive extends AbstractArchive { private final SevenZFile sevenZFile; private SevenZArchiveEntry currentEntry; public SevenZArchive(Path archivePath) throws IOException { super(archivePath); this.sevenZFile = new SevenZFile(Files.newByteChannel(getArchive())); } @Override protected ArchiveEntry nextEntry() throws IOException { currentEntry = sevenZFile.getNextEntry(); return currentEntry; } @Override protected InputStream getInputStream() throws IOException { return sevenZFile.getInputStream(currentEntry); } @Override protected boolean skipEntry() { return isMacOSMetaData(currentEntry.getName()); } @Override public void close() throws IOException { this.sevenZFile.close(); } }
package com.chinaunicom.asset.common.utils; import cn.hutool.core.lang.UUID; import com.chinaunicom.asset.common.exception.BaseException; import com.chinaunicom.asset.common.utils.compress.AbstractArchive; import lombok.extern.slf4j.Slf4j; import java.io.IOException; import java.nio.file.Files; import java.nio.file.Path; @Slf4j public class ArchiveFiles { private ArchiveFiles() { } public static Path decompress(Path archivePath) { // 检查文件存在 if (!Files.exists(archivePath) || Files.isDirectory(archivePath)) { throw new IllegalArgumentException("压缩文件不存在"); } // 在压缩文件的父目录生成目录,以存储解压后的文件 String decompressedDir = UUID.randomUUID().toString(true); Path decompressedPath = archivePath.getParent().resolve(decompressedDir); try (AbstractArchive archive = AbstractArchive.newArchive(archivePath)) { archive.decompress(decompressedPath); } catch (IOException e) { log.error(e.getMessage()); throw new BaseException("解压文件失败"); } catch (Exception e) { throw new BaseException(e); } return decompressedPath; } }
标签:JAVA,java,archivePath,解压缩,return,IOException,import,Path,写法 From: https://www.cnblogs.com/juniorMa/p/16951574.html