mirror of
https://github.com/kekingcn/kkFileView.git
synced 2026-03-30 01:56:36 +00:00
113 lines
4.9 KiB
Java
113 lines
4.9 KiB
Java
package cn.keking.service;
|
|
|
|
import cn.keking.config.ConfigConstants;
|
|
import cn.keking.model.FileAttribute;
|
|
import cn.keking.model.FileType;
|
|
import cn.keking.utils.RarUtils;
|
|
import cn.keking.web.filter.BaseUrlFilter;
|
|
import net.sf.sevenzipjbinding.ExtractOperationResult;
|
|
import net.sf.sevenzipjbinding.IInArchive;
|
|
import net.sf.sevenzipjbinding.SevenZip;
|
|
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.springframework.stereotype.Component;
|
|
|
|
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.net.URLEncoder;
|
|
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;
|
|
|
|
/**
|
|
* @author yudian-it
|
|
* create 2017/11/27
|
|
*/
|
|
@Component
|
|
public class CompressFileReader {
|
|
private final FileHandlerService fileHandlerService;
|
|
private static final String fileDir = ConfigConstants.getFileDir();
|
|
|
|
public CompressFileReader(FileHandlerService fileHandlerService) {
|
|
this.fileHandlerService = fileHandlerService;
|
|
}
|
|
|
|
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 folderName = filePath.replace(fileDir, ""); //修复压缩包 多重目录获取路径错误
|
|
if (fileAttribute.isCompressFile()) {
|
|
folderName = "_decompression" + folderName;
|
|
}
|
|
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();
|
|
for (final ISimpleInArchiveItem item : simpleInArchive.getArchiveItems()) {
|
|
if (!item.isFolder()) {
|
|
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) {
|
|
ExtractOperationResult result1 = ExtractOperationResult.valueOf("WRONG_PASSWORD");
|
|
if (result1.equals(result)) {
|
|
throw new Exception("Password");
|
|
}else {
|
|
throw new Exception("Failed to extract RAR file.");
|
|
}
|
|
}
|
|
|
|
FileType type = FileType.typeFromUrl(filePathInsideArchive.toString());
|
|
if (type.equals(FileType.PICTURE)) { //图片缓存到集合,为了特殊符号需要进行编码
|
|
imgUrls.add(baseUrl + URLEncoder.encode(fileName + packagePath+"/"+ folderPath.relativize(filePathInsideArchive).toString().replace("\\", "/"), "UTF-8"));
|
|
}
|
|
}
|
|
}
|
|
fileHandlerService.putImgCache(fileName + packagePath, imgUrls);
|
|
} catch (Exception 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;
|
|
}
|
|
|
|
|
|
} |