|
@@ -5,6 +5,7 @@ import cn.hutool.core.collection.ListUtil;
|
|
|
import cn.hutool.core.io.FileUtil;
|
|
|
import cn.hutool.core.util.StrUtil;
|
|
|
import com.github.junrar.Archive;
|
|
|
+import com.github.junrar.exception.RarException;
|
|
|
import com.github.junrar.rarfile.FileHeader;
|
|
|
import org.apache.commons.compress.archivers.ArchiveEntry;
|
|
|
import org.apache.commons.compress.archivers.ArchiveException;
|
|
@@ -12,12 +13,14 @@ import org.apache.commons.compress.archivers.ArchiveInputStream;
|
|
|
import org.apache.commons.compress.archivers.ArchiveStreamFactory;
|
|
|
import org.apache.commons.compress.archivers.zip.ZipArchiveEntry;
|
|
|
import org.apache.commons.compress.archivers.zip.ZipFile;
|
|
|
-import org.apache.commons.compress.utils.IOUtils;
|
|
|
+import org.apache.commons.io.IOUtils;
|
|
|
|
|
|
import java.io.*;
|
|
|
+import java.nio.charset.StandardCharsets;
|
|
|
import java.nio.file.Files;
|
|
|
import java.nio.file.Path;
|
|
|
import java.nio.file.Paths;
|
|
|
+import java.nio.file.StandardCopyOption;
|
|
|
import java.util.ArrayList;
|
|
|
import java.util.Enumeration;
|
|
|
import java.util.List;
|
|
@@ -46,35 +49,37 @@ public class ExcelUtil {
|
|
|
public static List<String> extractCompressedFiles(String zipFilePath, String destFilePath) throws IOException, ArchiveException {
|
|
|
List<String> filePathList = CollUtil.newArrayList();
|
|
|
|
|
|
- File destFile = FileUtil.file(destFilePath);
|
|
|
+ File destFile = FileUtil.file(destFilePath).getCanonicalFile();
|
|
|
if (!destFile.exists()) {
|
|
|
- destFile.mkdirs();
|
|
|
+ Files.createDirectories(destFile.toPath());
|
|
|
}
|
|
|
|
|
|
-
|
|
|
try (BufferedInputStream fis = new BufferedInputStream(new FileInputStream(zipFilePath));
|
|
|
- ArchiveInputStream ais = new ArchiveStreamFactory().createArchiveInputStream(fis)) {
|
|
|
+ ArchiveInputStream<? extends ArchiveEntry> ais = new ArchiveStreamFactory("UTF-8")
|
|
|
+ .createArchiveInputStream(ArchiveStreamFactory.ZIP, fis)) {
|
|
|
ArchiveEntry entry;
|
|
|
int i = 1;
|
|
|
while ((entry = ais.getNextEntry()) != null) {
|
|
|
+ // 跳过不可读条目(如加密文件)
|
|
|
+ if (!ais.canReadEntryData(entry)) {
|
|
|
+ continue;
|
|
|
+ }
|
|
|
String name = entry.getName();
|
|
|
- File entryFile;
|
|
|
- try {
|
|
|
- entryFile = FileUtil.file(destFilePath, name);
|
|
|
- } catch (Exception e) {
|
|
|
- String zipFilename = FileUtil.getName(destFilePath);
|
|
|
- String ext = FileUtil.extName(name);
|
|
|
- name = zipFilename + "_" + i + "." + ext;
|
|
|
- entryFile = FileUtil.file(destFilePath, name);
|
|
|
- i++;
|
|
|
+ File entryFile = FileUtil.file(destFilePath, name);
|
|
|
+
|
|
|
+ // 安全检查
|
|
|
+ if (!entryFile.toPath().normalize().startsWith(destFile.toPath())) {
|
|
|
+ throw new IOException("非法路径: " + name);
|
|
|
}
|
|
|
+
|
|
|
if (entry.isDirectory()) {
|
|
|
- entryFile.mkdirs();
|
|
|
+ Files.createDirectories(entryFile.toPath());
|
|
|
} else {
|
|
|
- try (FileOutputStream fos = new FileOutputStream(entryFile)) {
|
|
|
+ Files.createDirectories(entryFile.getParentFile().toPath());
|
|
|
+ try (OutputStream fos = Files.newOutputStream(entryFile.toPath())) {
|
|
|
IOUtils.copy(ais, fos);
|
|
|
- filePathList.add(entryFile.getPath());
|
|
|
}
|
|
|
+ filePathList.add(entryFile.getPath());
|
|
|
}
|
|
|
}
|
|
|
} catch (Exception e) {
|
|
@@ -90,44 +95,61 @@ public class ExcelUtil {
|
|
|
return filePathList;
|
|
|
}
|
|
|
|
|
|
- public static List<String> extractRar(String inputFilePath, String outputDirPath) {
|
|
|
+ public static List<String> extractRar(String inputFilePath, String outputDirPath) throws IOException {
|
|
|
List<String> fileList = new ArrayList<>();
|
|
|
- // 创建Archive对象,用于读取rar压缩文件格式
|
|
|
- try {
|
|
|
- String zipFilename = FileUtil.getName(inputFilePath);
|
|
|
- Archive archive = new Archive(new FileInputStream(inputFilePath));
|
|
|
- // 读取压缩文件中的所有子目录或子文件(FileHeader对象)
|
|
|
- List<FileHeader> fileHeaderList = archive.getFileHeaders();
|
|
|
- int i = 1;
|
|
|
- // 遍历子目录和子文件
|
|
|
- for (FileHeader fd : fileHeaderList) {
|
|
|
- String fileName = fd.getFileName();
|
|
|
- String ext = FileUtil.extName(fileName);
|
|
|
- fileName = zipFilename + "_" + i + "." + ext;
|
|
|
- i++;
|
|
|
- File f = FileUtil.file(outputDirPath + File.separator + fileName);
|
|
|
- if (fd.isDirectory()) {
|
|
|
- // 创建新子目录
|
|
|
- f.mkdirs();
|
|
|
- } else {
|
|
|
- // 创建新子文件
|
|
|
- f.createNewFile();
|
|
|
- // 获取压缩包中的子文件输出流
|
|
|
- InputStream in = archive.getInputStream(fd);
|
|
|
- // 复制文件输入流至新子文件
|
|
|
- FileUtil.copyFile(in, f);
|
|
|
- fileList.add(f.getAbsolutePath());
|
|
|
+ Path outputPath = Paths.get(outputDirPath).toRealPath();
|
|
|
+
|
|
|
+ try (FileInputStream fis = new FileInputStream(inputFilePath);
|
|
|
+ Archive archive = new Archive(fis)) { // 假设Archive支持try-with-resources
|
|
|
+
|
|
|
+ for (FileHeader entry : archive.getFileHeaders()) {
|
|
|
+ // 跳过目录条目(由文件创建逻辑自动生成目录)
|
|
|
+ if (entry.isDirectory()) continue;
|
|
|
+
|
|
|
+ // 处理文件名编码和路径
|
|
|
+ String fileName = new String(entry.getFileNameByteArray(), StandardCharsets.UTF_8);
|
|
|
+ Path targetPath = outputPath.resolve(fileName).normalize();
|
|
|
+
|
|
|
+ // 路径安全检查
|
|
|
+ if (!targetPath.startsWith(outputPath)) {
|
|
|
+ throw new IOException("检测到非法路径: " + fileName);
|
|
|
+ }
|
|
|
+
|
|
|
+ // 创建父目录
|
|
|
+ Files.createDirectories(targetPath.getParent());
|
|
|
+
|
|
|
+ // 处理文件重名
|
|
|
+ targetPath = resolveDuplicate(targetPath);
|
|
|
+
|
|
|
+ // 解压文件内容
|
|
|
+ try (InputStream entryStream = archive.getInputStream(entry)) {
|
|
|
+ Files.copy(entryStream, targetPath, StandardCopyOption.REPLACE_EXISTING);
|
|
|
+ fileList.add(targetPath.toAbsolutePath().toString());
|
|
|
}
|
|
|
}
|
|
|
- } catch (Exception e) {
|
|
|
+ } catch (UnsupportedEncodingException | RarException e) {
|
|
|
+ throw new IOException("解析RAR文件失败", e);
|
|
|
}
|
|
|
return fileList;
|
|
|
}
|
|
|
|
|
|
+ private static Path resolveDuplicate(Path path) {
|
|
|
+ if (!Files.exists(path)) return path;
|
|
|
+ String base = path.getFileName().toString();
|
|
|
+ String name = base.replaceFirst("[.][^.]+$", "");
|
|
|
+ String ext = base.substring(name.length());
|
|
|
+ int counter = 1;
|
|
|
+ while (true) {
|
|
|
+ Path newPath = path.resolveSibling(name + "_" + counter + ext);
|
|
|
+ if (!Files.exists(newPath)) return newPath;
|
|
|
+ counter++;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
public static List<String> extractSplitZip(String zipFilePath, String destFilePath) throws IOException {
|
|
|
List<String> resultList = ListUtil.list(false);
|
|
|
File file = new File(zipFilePath);
|
|
|
- try (ZipFile zipFile = new ZipFile(file)) {
|
|
|
+ try (ZipFile zipFile = ZipFile.builder().setFile(file).get()) {
|
|
|
Enumeration<ZipArchiveEntry> entries = zipFile.getEntries();
|
|
|
while (entries.hasMoreElements()) {
|
|
|
ZipArchiveEntry entry = entries.nextElement();
|