|
|
@@ -12,12 +12,18 @@ import net.sf.sevenzipjbinding.SevenZipException;
|
|
|
import net.sf.sevenzipjbinding.impl.RandomAccessFileInStream;
|
|
|
import net.sf.sevenzipjbinding.simple.ISimpleInArchive;
|
|
|
import net.sf.sevenzipjbinding.simple.ISimpleInArchiveItem;
|
|
|
-import org.apache.commons.io.IOUtils;
|
|
|
import org.springframework.stereotype.Component;
|
|
|
-import org.springframework.util.ObjectUtils;
|
|
|
|
|
|
-import java.io.*;
|
|
|
+import java.io.BufferedOutputStream;
|
|
|
+import java.io.FileOutputStream;
|
|
|
+import java.io.IOException;
|
|
|
+import java.io.OutputStream;
|
|
|
+import java.io.RandomAccessFile;
|
|
|
+import java.io.UnsupportedEncodingException;
|
|
|
import java.nio.charset.StandardCharsets;
|
|
|
+import java.nio.file.Files;
|
|
|
+import java.nio.file.Path;
|
|
|
+import java.nio.file.Paths;
|
|
|
import java.util.ArrayList;
|
|
|
import java.util.List;
|
|
|
|
|
|
@@ -37,73 +43,67 @@ public class CompressFileReader {
|
|
|
public String unRar(String filePath, String filePassword, String fileName, FileAttribute fileAttribute) throws Exception {
|
|
|
List<String> imgUrls = new ArrayList<>();
|
|
|
String baseUrl = BaseUrlFilter.getBaseUrl();
|
|
|
- String packagePath = "_"; //防止文件名重复 压缩包统一生成文件添加_符号
|
|
|
+ String packagePath = "_";
|
|
|
String folderName = filePath.replace(fileDir, ""); //修复压缩包 多重目录获取路径错误
|
|
|
- if (fileAttribute.isCompressFile()) { //压缩包文件 直接赋予路径 不予下载
|
|
|
- folderName = "_decompression" + folderName; //重新修改多重压缩包 生成文件路径
|
|
|
+ if (fileAttribute.isCompressFile()) {
|
|
|
+ folderName = "_decompression" + folderName;
|
|
|
}
|
|
|
- RandomAccessFile randomAccessFile = null;
|
|
|
- IInArchive inArchive = null;
|
|
|
- try {
|
|
|
- randomAccessFile = new RandomAccessFile(filePath, "r");
|
|
|
- inArchive = SevenZip.openInArchive(null, new RandomAccessFileInStream(randomAccessFile));
|
|
|
+
|
|
|
+ Path folderPath = Paths.get(fileDir, folderName + packagePath);
|
|
|
+ Files.createDirectories(folderPath);
|
|
|
+
|
|
|
+ try (RandomAccessFile randomAccessFile = new RandomAccessFile(filePath, "r");
|
|
|
+ IInArchive inArchive = SevenZip.openInArchive(null, new RandomAccessFileInStream(randomAccessFile))) {
|
|
|
+
|
|
|
ISimpleInArchive simpleInArchive = inArchive.getSimpleInterface();
|
|
|
- final String[] str = {null};
|
|
|
for (final ISimpleInArchiveItem item : simpleInArchive.getArchiveItems()) {
|
|
|
if (!item.isFolder()) {
|
|
|
- ExtractOperationResult result;
|
|
|
- String finalFolderName = folderName;
|
|
|
- result = item.extractSlow(data -> {
|
|
|
- try {
|
|
|
- str[0] = RarUtils.getUtf8String(item.getPath());
|
|
|
- if (RarUtils.isMessyCode(str[0])) {
|
|
|
- str[0] = new String(item.getPath().getBytes(StandardCharsets.ISO_8859_1), "gbk");
|
|
|
- }
|
|
|
- str[0] = str[0].replace("\\", File.separator); //Linux 下路径错误
|
|
|
- String str1 = str[0].substring(0, str[0].lastIndexOf(File.separator) + 1);
|
|
|
- File file = new File(fileDir, finalFolderName + packagePath + File.separator + str1);
|
|
|
- if (!file.exists()) {
|
|
|
- file.mkdirs();
|
|
|
- }
|
|
|
- OutputStream out = new FileOutputStream(fileDir + finalFolderName + packagePath + File.separator + str[0], true);
|
|
|
- IOUtils.write(data, out);
|
|
|
- out.close();
|
|
|
- } catch (Exception e) {
|
|
|
- e.printStackTrace();
|
|
|
- return Integer.parseInt(null);
|
|
|
+ final Path filePathInsideArchive = getFilePathInsideArchive(item, folderPath);
|
|
|
+ ExtractOperationResult result = item.extractSlow(data -> {
|
|
|
+ try (OutputStream out = new BufferedOutputStream(new FileOutputStream(filePathInsideArchive.toFile(), true))) {
|
|
|
+ out.write(data);
|
|
|
+ } catch (IOException e) {
|
|
|
+ throw new RuntimeException(e);
|
|
|
}
|
|
|
return data.length;
|
|
|
}, filePassword);
|
|
|
- if (result == ExtractOperationResult.OK) {
|
|
|
- FileType type = FileType.typeFromUrl(str[0]);
|
|
|
- if (type.equals(FileType.PICTURE)) {
|
|
|
- imgUrls.add(baseUrl + folderName + packagePath + "/" + str[0].replace("\\", "/"));
|
|
|
- }
|
|
|
- fileHandlerService.putImgCache(fileName + packagePath, imgUrls);
|
|
|
- } else {
|
|
|
- return null;
|
|
|
+
|
|
|
+ if (result != ExtractOperationResult.OK) {
|
|
|
+ throw new Exception("Failed to extract RAR file.");
|
|
|
+ }
|
|
|
+
|
|
|
+ FileType type = FileType.typeFromUrl(filePathInsideArchive.toString());
|
|
|
+ if (type.equals(FileType.PICTURE)) {
|
|
|
+ imgUrls.add(baseUrl + folderPath.relativize(filePathInsideArchive).toString().replace("\\", "/"));
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
- return folderName + packagePath;
|
|
|
+ fileHandlerService.putImgCache(fileName + packagePath, imgUrls);
|
|
|
} catch (Exception e) {
|
|
|
- throw new Exception(e);
|
|
|
- } finally {
|
|
|
- if (inArchive != null) {
|
|
|
- try {
|
|
|
- inArchive.close();
|
|
|
- } catch (SevenZipException e) {
|
|
|
- System.err.println("Error closing archive: " + e);
|
|
|
- }
|
|
|
- }
|
|
|
- if (randomAccessFile != null) {
|
|
|
- try {
|
|
|
- randomAccessFile.close();
|
|
|
- } catch (IOException e) {
|
|
|
- System.err.println("Error closing file: " + e);
|
|
|
- }
|
|
|
- }
|
|
|
+ throw new Exception("Error processing RAR file: " + e.getMessage(), e);
|
|
|
+ }
|
|
|
+ return folderName + packagePath;
|
|
|
+ }
|
|
|
+
|
|
|
+ private Path getFilePathInsideArchive(ISimpleInArchiveItem item, Path folderPath) throws SevenZipException, UnsupportedEncodingException {
|
|
|
+ String insideFileName = RarUtils.getUtf8String(item.getPath());
|
|
|
+ if (RarUtils.isMessyCode(insideFileName)) {
|
|
|
+ insideFileName = new String(item.getPath().getBytes(StandardCharsets.ISO_8859_1), "gbk");
|
|
|
+ }
|
|
|
+
|
|
|
+ // 正规化路径并验证是否安全
|
|
|
+ Path normalizedPath = folderPath.resolve(insideFileName).normalize();
|
|
|
+ if (!normalizedPath.startsWith(folderPath)) {
|
|
|
+ throw new SecurityException("Unsafe path detected: " + insideFileName);
|
|
|
}
|
|
|
+
|
|
|
+ try {
|
|
|
+ Files.createDirectories(normalizedPath.getParent());
|
|
|
+ } catch (IOException e) {
|
|
|
+ throw new RuntimeException("Failed to create directory: " + normalizedPath.getParent(), e);
|
|
|
+ }
|
|
|
+ return normalizedPath;
|
|
|
}
|
|
|
|
|
|
+
|
|
|
}
|