提交代码

This commit is contained in:
lilin 2025-03-24 10:05:42 +08:00
parent 5525ca35c1
commit 52b7c71fca

View File

@ -43,28 +43,15 @@ import com.yfd.platform.system.domain.SysDictionaryItems;
import com.yfd.platform.system.mapper.SysDictionaryItemsMapper;
import com.yfd.platform.utils.StringUtils;
import io.netty.channel.ChannelInboundHandlerAdapter;
import com.github.junrar.Archive;
import com.github.junrar.rarfile.FileHeader;
import com.github.junrar.exception.RarException;
import io.netty.handler.codec.compression.CompressionException;
import org.apache.commons.compress.archivers.ArchiveEntry;
import org.apache.commons.compress.archivers.ArchiveOutputStream;
import org.apache.commons.compress.archivers.sevenz.SevenZArchiveEntry;
import org.apache.commons.compress.archivers.sevenz.SevenZFile;
import org.apache.commons.compress.archivers.sevenz.SevenZOutputFile;
import org.apache.commons.compress.archivers.tar.TarArchiveEntry;
import org.apache.commons.compress.archivers.tar.TarArchiveInputStream;
import org.apache.commons.compress.archivers.tar.TarArchiveOutputStream;
import org.apache.commons.compress.archivers.zip.ZipArchiveEntry;
import org.apache.commons.compress.archivers.zip.ZipArchiveInputStream;
import org.apache.commons.compress.archivers.zip.ZipArchiveOutputStream;
import org.apache.commons.compress.compressors.bzip2.BZip2CompressorInputStream;
import org.apache.commons.compress.compressors.bzip2.BZip2CompressorOutputStream;
import org.apache.commons.compress.compressors.gzip.GzipCompressorInputStream;
import org.apache.commons.compress.compressors.gzip.GzipCompressorOutputStream;
import org.apache.commons.compress.compressors.xz.XZCompressorOutputStream;
import org.apache.commons.io.FileUtils;
import org.apache.commons.io.FilenameUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
@ -115,6 +102,7 @@ public class TsFilesServiceImpl extends ServiceImpl<TsFilesMapper, TsFiles> impl
// 从数据库获取的压缩类型列表
private List<String> compressSuffixes;
private final Set<String> addedEntries = new HashSet<>();
/**********************************
* 用途说明: 分页查询试验数据管理-文档内容
@ -1167,13 +1155,18 @@ public class TsFilesServiceImpl extends ServiceImpl<TsFilesMapper, TsFiles> impl
}
Path zipPath = generateZipPath(sourcePaths.get(0));
addedEntries.clear(); // 清空历史记录
try (ZipOutputStream zipOut = new ZipOutputStream(Files.newOutputStream(zipPath))) {
zipOut.setLevel(Deflater.DEFAULT_COMPRESSION);
for (Path sourcePath : sourcePaths) {
if (Files.isDirectory(sourcePath)) {
addDirectoryToZip(sourcePath, zipOut, sourcePath.getFileName().toString());
// 使用唯一化的 baseDir例如目录名
String baseDir = sourcePath.getFileName().toString();
addDirectoryToZip(sourcePath, zipOut, baseDir);
} else {
// 文件直接添加到根目录或指定唯一子目录
addFileToZip(sourcePath, zipOut, "");
}
}
@ -1188,23 +1181,46 @@ public class TsFilesServiceImpl extends ServiceImpl<TsFilesMapper, TsFiles> impl
}
private void addDirectoryToZip(Path dir, ZipOutputStream zipOut, String baseDir) throws IOException {
final Path sourceDir = dir;
Files.walkFileTree(dir, new SimpleFileVisitor<Path>() {
@Override
public FileVisitResult preVisitDirectory(Path dir, BasicFileAttributes attrs) throws IOException {
String entryName = baseDir + "/" + dir.relativize(dir).toString().replace("\\", "/") + "/";
ZipEntry entry = new ZipEntry(entryName);
zipOut.putNextEntry(entry);
zipOut.closeEntry();
public FileVisitResult preVisitDirectory(Path currentDir, BasicFileAttributes attrs) throws IOException {
// 跳过源目录自身由外部显式添加
if (currentDir.equals(sourceDir)) {
return FileVisitResult.CONTINUE;
}
// 生成相对路径的条目名称
Path relativePath = sourceDir.relativize(currentDir);
String entryName = baseDir + "/" + relativePath.toString().replace("\\", "/") + "/";
// 确保条目唯一性
addUniqueDirectoryEntry(entryName, zipOut);
return FileVisitResult.CONTINUE;
}
@Override
public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) throws IOException {
String entryName = baseDir + "/" + dir.relativize(file).toString().replace("\\", "/");
Path relativePath = sourceDir.relativize(file);
String entryName = baseDir + "/" + relativePath.toString().replace("\\", "/");
addFileEntry(file, entryName, zipOut);
return FileVisitResult.CONTINUE;
}
});
// 显式添加根目录条目确保至少存在一个目录条目
String rootEntry = baseDir + "/";
addUniqueDirectoryEntry(rootEntry, zipOut);
}
private void addUniqueDirectoryEntry(String entryName, ZipOutputStream zipOut) throws IOException {
if (!addedEntries.contains(entryName)) {
ZipEntry entry = new ZipEntry(entryName);
zipOut.putNextEntry(entry);
zipOut.closeEntry();
addedEntries.add(entryName);
}
}
private void addFileToZip(Path file, ZipOutputStream zipOut, String baseDir) throws IOException {
@ -1213,6 +1229,11 @@ public class TsFilesServiceImpl extends ServiceImpl<TsFilesMapper, TsFiles> impl
}
private void addFileEntry(Path file, String entryName, ZipOutputStream zipOut) throws IOException {
if (addedEntries.contains(entryName)) {
LOGGER.warn("跳过重复条目: {}", entryName);
return;
}
LOGGER.debug("添加文件条目: {} (大小: {} 字节)", entryName, Files.size(file));
ZipEntry entry = new ZipEntry(entryName);
entry.setSize(Files.size(file));
@ -1228,6 +1249,7 @@ public class TsFilesServiceImpl extends ServiceImpl<TsFilesMapper, TsFiles> impl
}
zipOut.closeEntry();
addedEntries.add(entryName);
}
private Path generateZipPath(Path sourcePath) {
@ -1247,7 +1269,8 @@ public class TsFilesServiceImpl extends ServiceImpl<TsFilesMapper, TsFiles> impl
ZipEntry entry = entries.nextElement();
try (InputStream is = zipFile.getInputStream(entry)) {
byte[] buffer = new byte[1024];
while (is.read(buffer) != -1) {} // 读取条目内容
while (is.read(buffer) != -1) {
} // 读取条目内容
}
}
@ -1262,7 +1285,8 @@ public class TsFilesServiceImpl extends ServiceImpl<TsFilesMapper, TsFiles> impl
private void deleteQuietly(Path path) {
try {
Files.deleteIfExists(path);
} catch (IOException ignored) {}
} catch (IOException ignored) {
}
}
/**
@ -1277,13 +1301,6 @@ public class TsFilesServiceImpl extends ServiceImpl<TsFilesMapper, TsFiles> impl
}
// ================== TAR.GZ格式压缩实现 ==================
private boolean compressToTarGz(List<Path> sourcePaths) throws IOException {
boolean success = true;
@ -1420,7 +1437,7 @@ public class TsFilesServiceImpl extends ServiceImpl<TsFilesMapper, TsFiles> impl
// 1. 获取压缩包记录
TsFiles zipFileRecord = tsFilesMapper.selectById(id);
String zipName = zipFileRecord.getFileName(); // 示例222
String zipName = getFileNameWithoutExtension(zipFileRecord.getFileName()); // 示例222
try {
// 2. 判断压缩包类型单文件还是文件夹
Path zipFilePath = Paths.get(storageSourceConfig.getValue(), zipFileRecord.getWorkPath(), zipFileRecord.getFileName());
@ -1429,12 +1446,8 @@ public class TsFilesServiceImpl extends ServiceImpl<TsFilesMapper, TsFiles> impl
// // 4. 构建解压目标路径
Path destRoot;
if (hasFolder) {
// 动态去掉 .zip 后缀仅用于路径构建
String folderName = zipName.toLowerCase().endsWith(".zip")
? zipName.substring(0, zipName.length() - 4)
: zipName;
// 如果有文件夹创建子目录 E:/yun/333/222/
destRoot = Paths.get(storageSourceConfig.getValue(), decompressionPath, folderName);
destRoot = Paths.get(storageSourceConfig.getValue(), decompressionPath, zipName);
} else {
// 如果只有文件直接解压到目标目录 E:/yun/333/
destRoot = Paths.get(storageSourceConfig.getValue(), decompressionPath);
@ -1460,7 +1473,7 @@ public class TsFilesServiceImpl extends ServiceImpl<TsFilesMapper, TsFiles> impl
);
String rootFolderId = rootFolder.getId();
// 7. 处理子内容路径从/333/222/开始
// 7. 处理子内容路径从/333/222/开始 关键点 所有的文件夹都是上级路径 文件是上级路径加名称
processFolderContents(
unzippedRoot,
rootFolderId,
@ -1577,7 +1590,7 @@ public class TsFilesServiceImpl extends ServiceImpl<TsFilesMapper, TsFiles> impl
folderRecord.setTaskId(taskId);
folderRecord.setParentId(parentId); // 父ID是222的ID
folderRecord.setFileName(child.getName());
folderRecord.setWorkPath(childWorkPath); // /333/222/555/
folderRecord.setWorkPath(folderWorkPath); // /333/222/555/
folderRecord.setIsFile("FOLDER");
folderRecord.setFileSize("0");
folderRecord.setUploadTime(new Timestamp(System.currentTimeMillis()));
@ -1587,7 +1600,7 @@ public class TsFilesServiceImpl extends ServiceImpl<TsFilesMapper, TsFiles> impl
processFolderContents(
child,
folderRecord.getId(),
folderWorkPath,
childWorkPath,
taskId,
nodeId,
uploader