提交代码tar tar.gz 7z压缩解压缩

This commit is contained in:
lilin 2025-03-26 09:54:51 +08:00
parent a477ae3952
commit 9eaa8c300d

View File

@ -6,6 +6,8 @@ import cn.hutool.core.collection.CollUtil;
import java.nio.charset.StandardCharsets;
import java.nio.file.*;
import java.nio.file.attribute.BasicFileAttributes;
import java.nio.file.attribute.PosixFilePermission;
import java.nio.file.attribute.PosixFilePermissions;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.text.SimpleDateFormat;
@ -46,6 +48,7 @@ import io.netty.channel.ChannelInboundHandlerAdapter;
import net.sf.jsqlparser.expression.LongValue;
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;
@ -244,6 +247,22 @@ public class TsFilesServiceImpl extends ServiceImpl<TsFilesMapper, TsFiles> impl
// 获取文件扩展名的方法
private String getFileExtension(String filename) {
if (filename.endsWith(".tar.gz")) {
return ".tar.gz";
}
// 检查是否是 .tar 格式
if (filename.endsWith(".tar")) {
return ".tar"; // 去掉 ".tar"
}
// 检查是否是 .zip 格式
if (filename.endsWith(".zip")) {
return ".zip"; // 去掉 ".zip"
}
// 检查是否是 .7z 格式
if (filename.endsWith(".7z")) {
return ".7z"; // 去掉 ".7z"
}
if (filename != null && filename.contains(".")) {
return filename.substring(filename.lastIndexOf("."));
}
@ -1215,13 +1234,23 @@ public class TsFilesServiceImpl extends ServiceImpl<TsFilesMapper, TsFiles> impl
if (pathSegments.isEmpty() || !pathSegments.get(0).equals(nodeId)) {
throw new RuntimeException("路径必须包含当前节点ID");
}
String nodePath = "/" + nodeId + "/";
if (compressedPath.equals(nodePath)) {
return "00";
}
// 提取实际要处理的目录层级去掉开头的nodeId
List<String> dirSegments = pathSegments.subList(1, pathSegments.size());
List<String> dirSegments = null;
if (pathSegments.size() > 1) {
// 如果 pathSegments 大于 1去掉 nodeId
dirSegments = pathSegments.subList(1, pathSegments.size());
}
if (dirSegments.isEmpty()) {
throw new RuntimeException("路径缺少有效目录层级");
}
// 2. 初始化根目录信息基于nodeId
String parentId = "00"; // 根目录的父ID为0
String baseFsPath = "/" + nodeId + "/"; // 本地存储基础路径
@ -1296,10 +1325,12 @@ public class TsFilesServiceImpl extends ServiceImpl<TsFilesMapper, TsFiles> impl
switch (compressedFormat.toUpperCase()) {
case "ZIP":
return compressToZip(sourcePaths, outputPath);
case "TAR":
return compressToTar(sourcePaths, outputPath);
case "TAR.GZ":
return compressToTarGz(sourcePaths);
// case "7Z":
// return compressTo7z(sourcePaths);
return compressToTarGz(sourcePaths, outputPath);
case "7Z":
return compressTo7z(sourcePaths, outputPath);
default:
throw new IllegalArgumentException("不支持的压缩格式: " + compressedFormat);
}
@ -1436,10 +1467,6 @@ public class TsFilesServiceImpl extends ServiceImpl<TsFilesMapper, TsFiles> impl
addedEntries.add(entryName);
}
private Path generateZipPath(Path sourcePath) {
String baseName = sourcePath.getFileName().toString().replaceFirst("[.][^.]+$", "");
return sourcePath.resolveSibling(baseName + ".zip");
}
private boolean validateZip(Path zipPath) {
try (ZipFile zipFile = new ZipFile(zipPath.toFile())) {
@ -1485,77 +1512,186 @@ public class TsFilesServiceImpl extends ServiceImpl<TsFilesMapper, TsFiles> impl
}
// ================== TAR.GZ格式压缩实现 ==================
private boolean compressToTarGz(List<Path> sourcePaths) throws IOException {
boolean success = true;
// ================== TAR格式压缩实现 ==================
/**
* 压缩为纯TAR格式不进行GZ压缩
*
* @param sourcePaths 要压缩的源路径列表文件或目录
* @param outputPath 输出文件路径必须以.tar结尾
* @return 是否压缩成功
* @throws IOException 文件操作异常
*/
private boolean compressToTar(List<Path> sourcePaths, Path outputPath) throws IOException {
try (TarArchiveOutputStream tarOut = new TarArchiveOutputStream(Files.newOutputStream(outputPath))) {
tarOut.setLongFileMode(TarArchiveOutputStream.LONGFILE_POSIX);
for (Path sourcePath : sourcePaths) {
Path tarGzPath = getCompressedFilePath(sourcePath, "tar.gz");
try (OutputStream fos = Files.newOutputStream(tarGzPath);
// 关键修改始终使用源路径的父目录作为basePath
Path basePath = sourcePath.getParent();
Files.walkFileTree(sourcePath, new SimpleFileVisitor<Path>() {
@Override
public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) throws IOException {
String entryName = basePath.relativize(file).toString().replace(File.separator, "/");
addFileToTar(file, entryName, tarOut);
return FileVisitResult.CONTINUE;
}
@Override
public FileVisitResult preVisitDirectory(Path dir, BasicFileAttributes attrs) throws IOException {
if (!dir.equals(sourcePath)) { // 不跳过源目录本身
String dirName = basePath.relativize(dir).toString().replace(File.separator, "/") + "/";
addDirToTar(dir, dirName, tarOut);
}
return FileVisitResult.CONTINUE;
}
});
}
tarOut.finish();
return true;
}
}
// 辅助方法添加文件条目
private void addFileToTar(Path file, String entryName, TarArchiveOutputStream tarOut) throws IOException {
TarArchiveEntry entry = new TarArchiveEntry(file.toFile(), entryName);
entry.setSize(Files.size(file));
tarOut.putArchiveEntry(entry);
try (InputStream is = Files.newInputStream(file)) {
IOUtils.copy(is, tarOut);
}
tarOut.closeArchiveEntry();
}
// 辅助方法添加目录条目
private void addDirToTar(Path dir, String dirName, TarArchiveOutputStream tarOut) throws IOException {
TarArchiveEntry entry = new TarArchiveEntry(dir.toFile(), dirName);
tarOut.putArchiveEntry(entry);
tarOut.closeArchiveEntry();
}
// ================== TAR.GZ格式压缩实现 ==================
private boolean compressToTarGz(List<Path> sourcePaths, Path outputPath) throws IOException {
try (OutputStream fos = Files.newOutputStream(outputPath);
GzipCompressorOutputStream gzos = new GzipCompressorOutputStream(fos);
TarArchiveOutputStream tarOut = new TarArchiveOutputStream(gzos)) {
// 设置支持长文件名超过100字符
tarOut.setLongFileMode(TarArchiveOutputStream.LONGFILE_POSIX);
processEntries(sourcePath, (entryName, isDir) -> {
Path filePath = sourcePath.resolve(entryName);
TarArchiveEntry entry = new TarArchiveEntry(filePath.toFile(), entryName);
entry.setSize(isDir ? 0 : Files.size(filePath));
tarOut.putArchiveEntry(entry);
if (!isDir) {
try (InputStream input = Files.newInputStream(filePath)) {
IOUtils.copy(input, tarOut);
// 遍历所有源路径并添加到压缩文件
for (Path path : sourcePaths) {
addToTarArchive(path, tarOut, "");
}
}
tarOut.closeArchiveEntry();
});
tarOut.finish();
return true;
} catch (Exception e) {
success = false;
e.printStackTrace();
return false;
}
}
return success;
}
// ================== 7Z格式压缩实现 ==================
// private boolean compressTo7z(List<Path> sourcePaths) throws IOException {
// boolean success = true;
// for (Path sourcePath : sourcePaths) {
// Path sevenZPath = getCompressedFilePath(sourcePath, "7z");
// try (SevenZOutputFile sevenZOutput = new SevenZOutputFile(sevenZPath.toFile())) {
//
// processEntries(sourcePath, (entryName, isDir) -> {
// SevenZArchiveEntry entry = sevenZOutput.createEntry();
// entry.setName(entryName);
// entry.setDirectory(isDir);
//
// if (!isDir) {
// Path filePath = sourcePath.resolve(entryName);
// entry.setSize(Files.size(filePath));
// sevenZOutput.putArchiveEntry(entry);
//
// try (InputStream input = Files.newInputStream(filePath)) {
// byte[] buffer = new byte[8192];
// int len;
// while ((len = input.read(buffer)) != -1) {
// sevenZOutput.write(buffer, 0, len);
// }
// }
//
// sevenZOutput.closeArchiveEntry();
// }
// });
//
// } catch (Exception e) {
// success = false;
// e.printStackTrace();
// }
// }
// return success;
// }
/**
* 递归添加文件到TAR压缩流
*
* @param source 当前要添加的路径
* @param tarOut TAR输出流
* @param parentDir 在压缩文件中的父目录路径用于保持目录结构
*/
private void addToTarArchive(Path source, TarArchiveOutputStream tarOut, String parentDir) throws IOException {
// 获取文件在压缩包中的入口名称替换路径分隔符为/
String entryName = parentDir + source.getFileName().toString().replace(File.separator, "/");
// 处理目录
if (Files.isDirectory(source)) {
entryName += "/"; // 目录需要以/结尾
TarArchiveEntry dirEntry = new TarArchiveEntry(source.toFile(), entryName);
tarOut.putArchiveEntry(dirEntry);
tarOut.closeArchiveEntry();
// 递归处理子目录
try (DirectoryStream<Path> children = Files.newDirectoryStream(source)) {
for (Path child : children) {
addToTarArchive(child, tarOut, entryName);
}
}
}
// 处理文件
else {
TarArchiveEntry fileEntry = new TarArchiveEntry(source.toFile(), entryName);
fileEntry.setSize(Files.size(source));
tarOut.putArchiveEntry(fileEntry);
try (InputStream input = Files.newInputStream(source)) {
IOUtils.copy(input, tarOut);
}
tarOut.closeArchiveEntry();
}
}
/**
* 压缩为7z格式
*
* @param sourcePaths 要压缩的源路径列表
* @param outputPath 输出文件路径必须包含文件名
*/
private boolean compressTo7z(List<Path> sourcePaths, Path outputPath) throws IOException {
try (SevenZOutputFile sevenZOutput = new SevenZOutputFile(outputPath.toFile())) {
// 遍历所有源路径并添加到压缩文件
for (Path path : sourcePaths) {
addTo7zArchive(path, sevenZOutput, "");
}
return true;
} catch (Exception e) {
e.printStackTrace();
return false;
}
}
/**
* 递归添加文件到7z压缩流
*
* @param source 当前要添加的路径
* @param sevenZOutput 7z输出流
* @param parentDir 在压缩文件中的父目录路径用于保持目录结构
*/
private void addTo7zArchive(Path source, SevenZOutputFile sevenZOutput, String parentDir) throws IOException {
// 生成压缩包内条目名称
String entryName = parentDir.isEmpty()
? source.getFileName().toString().replace(File.separator, "/")
: parentDir + "/" + source.getFileName().toString().replace(File.separator, "/");
// 创建压缩条目并设置属性
SevenZArchiveEntry entry = new SevenZArchiveEntry();
entry.setName(entryName);
entry.setDirectory(Files.isDirectory(source));
sevenZOutput.putArchiveEntry(entry);
// 如果是文件则写入内容
if (!entry.isDirectory()) {
try (InputStream input = Files.newInputStream(source)) {
byte[] buffer = new byte[8192];
int len;
while ((len = input.read(buffer)) > 0) {
sevenZOutput.write(buffer, 0, len);
}
}
}
sevenZOutput.closeArchiveEntry();
// 递归处理子目录
if (entry.isDirectory()) {
try (DirectoryStream<Path> children = Files.newDirectoryStream(source)) {
for (Path child : children) {
addTo7zArchive(child, sevenZOutput, entryName);
}
}
}
}
// ================== 通用工具方法 ==================
private interface EntryProcessor {
@ -1862,6 +1998,8 @@ public class TsFilesServiceImpl extends ServiceImpl<TsFilesMapper, TsFiles> impl
return unzipFile(zipFilePath, baseDir);
} else if (fileName.endsWith(".tar.gz")) {
return unTarGzFile(zipFilePath, baseDir);
} else if (ext.equals(".tar")) {
return unTarFile(zipFilePath, baseDir);
} else if (ext.equals(".7z")) {
return un7zFile(zipFilePath, baseDir);
} else {
@ -1878,6 +2016,8 @@ public class TsFilesServiceImpl extends ServiceImpl<TsFilesMapper, TsFiles> impl
return hasFolderInZip(zipFilePath);
} else if (fileName.endsWith(".tar.gz")) {
return hasFolderInTarGz(zipFilePath);
} else if (ext.equals(".tar")) {
return hasFolderInTar(zipFilePath);
} else if (ext.equals(".7z")) {
return hasFolderIn7z(zipFilePath);
} else {
@ -1910,6 +2050,38 @@ public class TsFilesServiceImpl extends ServiceImpl<TsFilesMapper, TsFiles> impl
}
}
// 新增TAR格式文件夹判断
private boolean hasFolderInTar(Path filePath) throws IOException {
// 参数校验
if (!filePath.toString().toLowerCase().endsWith(".tar")) {
throw new IllegalArgumentException("输入文件必须以.tar结尾");
}
if (!Files.exists(filePath)) {
throw new FileNotFoundException("TAR文件不存在: " + filePath);
}
try (InputStream fis = Files.newInputStream(filePath);
TarArchiveInputStream tis = new TarArchiveInputStream(fis)) {
TarArchiveEntry entry;
while ((entry = tis.getNextTarEntry()) != null) {
// 忽略MAC系统元数据目录
if (entry.getName().startsWith("__MACOSX/")) {
continue;
}
// 发现目录立即返回true
if (entry.isDirectory()) {
// 额外验证确保不是空名称或根目录标记
if (!entry.getName().trim().isEmpty() && !entry.getName().equals("./")) {
return true;
}
}
}
return false;
}
}
// 新增7Z格式文件夹判断
private boolean hasFolderIn7z(Path filePath) throws IOException {
try (SevenZFile szFile = new SevenZFile(filePath.toFile())) {
@ -2003,23 +2175,93 @@ public class TsFilesServiceImpl extends ServiceImpl<TsFilesMapper, TsFiles> impl
}
// 新增TAR.GZ解压实现保持相同路径逻辑
/**
* 解压TAR.GZ格式文件含GZIP压缩的TAR包
*
* @param sourcePath 压缩文件路径必须是以.tar.gz结尾的文件
* @param baseDir 解压目标目录路径
* @return 解压后的根目录File对象
* @throws IOException 文件操作异常或安全校验失败
*/
private File unTarGzFile(Path sourcePath, String baseDir) throws IOException {
Path destRoot = Paths.get(baseDir);
// 参数校验
if (!sourcePath.toString().toLowerCase().endsWith(".tar.gz")) {
throw new IllegalArgumentException("文件必须是 .tar.gz 格式");
}
Path destRoot = Paths.get(baseDir).toAbsolutePath();
Files.createDirectories(destRoot);
try (InputStream fi = Files.newInputStream(sourcePath);
InputStream gi = new GzipCompressorInputStream(fi);
TarArchiveInputStream ti = new TarArchiveInputStream(gi)) {
try (TarArchiveInputStream tis = new TarArchiveInputStream(
new GzipCompressorInputStream(Files.newInputStream(sourcePath)))) {
TarArchiveEntry entry;
while ((entry = ti.getNextTarEntry()) != null) {
// 保持相同过滤逻辑
if (entry.getName().startsWith("__MACOSX/")) {
while ((entry = tis.getNextTarEntry()) != null) {
// 跳过无效条目
if (entry.getName() == null || entry.getName().contains("__MACOSX")) {
continue;
}
Path targetPath = destRoot.resolve(entry.getName()).normalize();
// 路径规范化
String normalizedPath = normalizePathtargz(entry.getName(), sourcePath.getFileName().toString());
if (normalizedPath.isEmpty()) continue;
Path targetPath = destRoot.resolve(normalizedPath).normalize();
validatePath(targetPath, destRoot);
// 处理目录/文件
if (entry.isDirectory()) {
Files.createDirectories(targetPath);
} else {
Files.createDirectories(targetPath.getParent());
try (OutputStream os = Files.newOutputStream(targetPath)) {
IOUtils.copy(tis, os);
}
}
// 保留Unix权限
if (!System.getProperty("os.name").toLowerCase().contains("win")) {
Files.setPosixFilePermissions(targetPath,
PosixFilePermissions.fromString(getPosixMode(entry.getMode())));
}
}
}
return destRoot.toFile();
}
// 转换Unix权限位
private String getPosixMode(int mode) {
return String.format("%s%s%s %s%s%s %s%s%s",
(mode & 0400) != 0 ? "r" : "-", (mode & 0200) != 0 ? "w" : "-", (mode & 0100) != 0 ? "x" : "-",
(mode & 0040) != 0 ? "r" : "-", (mode & 0020) != 0 ? "w" : "-", (mode & 0010) != 0 ? "x" : "-",
(mode & 0004) != 0 ? "r" : "-", (mode & 0002) != 0 ? "w" : "-", (mode & 0001) != 0 ? "x" : "-");
}
/**
* 验证目标路径安全性防止路径穿越攻击
*/
private void validatePath(Path targetPath, Path destRoot) throws IOException {
if (!targetPath.normalize().startsWith(destRoot.normalize())) {
throw new IOException("危险路径: " + targetPath);
}
}
/**
* 解压TAR文件自动处理嵌套目录问题
*
* @param sourcePath 源TAR文件路径
* @param baseDir 目标目录解压到此目录下
* @return 解压后的根目录
*/
private File unTarFile(Path sourcePath, String baseDir) throws IOException {
Path destRoot = Paths.get(baseDir).toAbsolutePath();
Files.createDirectories(destRoot);
try (TarArchiveInputStream tis = new TarArchiveInputStream(Files.newInputStream(sourcePath))) {
TarArchiveEntry entry;
while ((entry = tis.getNextTarEntry()) != null) {
// 处理路径移除可能重复的顶层目录名
String normalizedName = normalizeEntryPath(entry.getName(), sourcePath.getFileName().toString());
Path targetPath = destRoot.resolve(normalizedName).normalize();
validatePathSafety(targetPath, destRoot);
if (entry.isDirectory()) {
@ -2027,7 +2269,7 @@ public class TsFilesServiceImpl extends ServiceImpl<TsFilesMapper, TsFiles> impl
} else {
Files.createDirectories(targetPath.getParent());
try (OutputStream os = Files.newOutputStream(targetPath)) {
IOUtils.copy(ti, os);
IOUtils.copy(tis, os);
}
}
}
@ -2035,22 +2277,85 @@ public class TsFilesServiceImpl extends ServiceImpl<TsFilesMapper, TsFiles> impl
return destRoot.toFile();
}
// 新增7Z解压实现保持相同路径逻辑
/**
* 智能规范化压缩包内路径
* @param entryPath 压缩包内原始路径
* @param archiveFilename 压缩包文件名"111.tar.gz"
* @return 处理后的路径
*/
private String normalizeEntryPath(String entryPath, String archiveFilename) {
// 基础处理移除开头的./和多余的/
String path = entryPath.replaceAll("^\\./", "").replaceAll("/+", "/");
// 获取预期的根目录名去掉压缩扩展名
String baseName = archiveFilename.replaceFirst("\\.(tar|gz|7z|tar\\.gz)$", "");
// 情况1路径直接以baseName开头"111/22/33.txt"
if (path.startsWith(baseName + "/")) {
return path.substring(baseName.length() + 1);
}
// 情况2路径已经是扁平结构"22/33.txt"
return path;
}
/**
* 安全规范化压缩包内路径
* @param entryPath 原始路径 "111/222/3.txt"
* @param archiveName 压缩包文件名 "111.7z"
* @return 规范化后的路径 "222/3.txt"
*/
private String normalizePathtargz(String entryPath, String archiveName) {
if (entryPath == null || entryPath.trim().isEmpty()) return "";
// 统一路径分隔符并清理特殊字符
String path = entryPath.replace("\\", "/")
.replaceAll("^\\./", "")
.replaceAll("/+", "/")
.trim();
// 移除压缩包文件名对应的顶层目录如果存在
String baseName = archiveName.replaceAll("\\.(tar\\.gz|gz|tar|7z)$", "");
if (!baseName.isEmpty() && path.startsWith(baseName + "/")) {
return path.substring(baseName.length() + 1);
}
return path;
}
/**
* 解压7Z格式文件
*
* @param sourcePath 压缩文件路径必须是以.7z结尾的文件
* @param baseDir 解压目标目录路径
* @return 解压后的根目录File对象
*/
private File un7zFile(Path sourcePath, String baseDir) throws IOException {
Path destRoot = Paths.get(baseDir);
// 参数校验
if (!sourcePath.getFileName().toString().toLowerCase().endsWith(".7z")) {
throw new IllegalArgumentException("必须是.7z文件");
}
Path destRoot = Paths.get(baseDir).toAbsolutePath();
Files.createDirectories(destRoot);
try (SevenZFile szFile = new SevenZFile(sourcePath.toFile())) {
SevenZArchiveEntry entry;
while ((entry = szFile.getNextEntry()) != null) {
// 保持相同过滤逻辑
if (entry.getName().startsWith("__MACOSX/")) {
// 跳过无效条目
if (entry.getName() == null || entry.getName().contains("__MACOSX")) {
continue;
}
Path targetPath = destRoot.resolve(entry.getName()).normalize();
// 关键修复使用智能路径规范化
String normalizedPath = smartNormalizePath7z(entry.getName(), sourcePath.getFileName().toString());
if (normalizedPath.isEmpty()) {
continue; // 跳过根目录条目
}
Path targetPath = destRoot.resolve(normalizedPath).normalize();
validatePathSafety(targetPath, destRoot);
// 处理文件/目录
if (entry.isDirectory()) {
Files.createDirectories(targetPath);
} else {
@ -2068,6 +2373,67 @@ public class TsFilesServiceImpl extends ServiceImpl<TsFilesMapper, TsFiles> impl
return destRoot.toFile();
}
/**
* 智能路径规范化修复7z/tar.gz多层级问题
* @param entryPath 压缩包内原始路径 "111/222/3.txt"
* @param archiveName 压缩包文件名 "111.7z"
* @return 规范化后的路径 "222/3.txt"
*/
private String smartNormalizePath7z(String entryPath, String archiveName) {
if (entryPath == null || entryPath.trim().isEmpty()) {
return "";
}
// 统一路径分隔符
String path = entryPath.replace("\\", "/")
.replaceAll("/+", "/")
.trim();
// 移除压缩包名称对应的冗余顶层目录
String baseName = archiveName.replaceAll("\\.(7z|tar\\.gz|tar|zip)$", "");
if (!baseName.isEmpty()) {
// 情况1路径直接以baseName开头 "111/222/3.txt"
if (path.startsWith(baseName + "/")) {
return path.substring(baseName.length() + 1);
}
// 情况2路径是baseName自身 "111/"
if (path.equals(baseName) || path.equals(baseName + "/")) {
return "";
}
}
return path;
}
/**
* 设置文件权限兼容Unix系统
*
* @param path 目标路径
* @param entry 压缩条目含权限信息
*/
private void setFilePermissions(Path path, TarArchiveEntry entry) throws IOException {
if (!System.getProperty("os.name").toLowerCase().contains("win")) {
Set<PosixFilePermission> perms = PosixFilePermissions.fromString(
getPosixPermissions(entry.getMode())
);
Files.setPosixFilePermissions(path, perms);
}
}
/**
* 转换Unix权限位为rwx格式
*
* @param mode 权限位如0755
*/
private String getPosixPermissions(int mode) {
return String.format("%s%s%s",
(mode & 0400) != 0 ? "r" : "-",
(mode & 0200) != 0 ? "w" : "-",
(mode & 0100) != 0 ? "x" : "-"
);
}
/**
@ -2083,6 +2449,23 @@ public class TsFilesServiceImpl extends ServiceImpl<TsFilesMapper, TsFiles> impl
* 获取无扩展名的文件名
*/
private String getFileNameWithoutExtension(String fileName) {
// 检查是否是 .tar.gz 格式
if (fileName.endsWith(".tar.gz")) {
return fileName.substring(0, fileName.length() - 7); // 去掉 ".tar.gz"
}
// 检查是否是 .tar 格式
if (fileName.endsWith(".tar")) {
return fileName.substring(0, fileName.length() - 4); // 去掉 ".tar"
}
// 检查是否是 .zip 格式
if (fileName.endsWith(".zip")) {
return fileName.substring(0, fileName.length() - 4); // 去掉 ".zip"
}
// 检查是否是 .7z 格式
if (fileName.endsWith(".7z")) {
return fileName.substring(0, fileName.length() - 3); // 去掉 ".7z"
}
// 对其他普通文件名直接返回去除扩展名的部分
int dotIndex = fileName.lastIndexOf('.');
return (dotIndex == -1) ? fileName : fileName.substring(0, dotIndex);
}
@ -2328,7 +2711,7 @@ public class TsFilesServiceImpl extends ServiceImpl<TsFilesMapper, TsFiles> impl
String key = generateMapKey(minioFile);
if (localMap.containsKey(key)) {
FileItemResult localFile = localMap.get(key);
checkFileConsistency(minioFile, localFile, filePath, bucketName, sizeMismatches, md5Mismatches);
checkFileConsistency(minioFile, localFile, filePath, bucketName, sizeMismatches, md5Mismatches, nodeId);
}
});
@ -2389,7 +2772,11 @@ public class TsFilesServiceImpl extends ServiceImpl<TsFilesMapper, TsFiles> impl
String basePath,
String bucketName,
List<String> sizeMismatches,
List<FileItemResult> md5Mismatches) {
List<FileItemResult> md5Mismatches, String nodeId) {
minioFile.setPath("/" + nodeId + minioFile.getPath());
localFile.setPath("/" + nodeId + localFile.getPath());
File localFileObj = new File(basePath + minioFile.getPath(), localFile.getName());
if (localFileObj.isDirectory()) {
LOGGER.warn("跳过文件夹: {}", localFileObj.getAbsolutePath());
@ -3667,7 +4054,7 @@ public class TsFilesServiceImpl extends ServiceImpl<TsFilesMapper, TsFiles> impl
public String processingPath(String Path, String nodeId) {
String newWorkPath = "";
if(Path == null || nodeId == null){
if (Path == null || nodeId == null) {
return newWorkPath;
}
// 获取原始路径和 nodeId