提交代码
This commit is contained in:
parent
62cf72359a
commit
b08961f2d3
@ -116,7 +116,7 @@ public class TsFilesController {
|
|||||||
@ApiOperation("新增试验数据管理文件夹")
|
@ApiOperation("新增试验数据管理文件夹")
|
||||||
@ResponseBody
|
@ResponseBody
|
||||||
@PreAuthorize("@el.check('add:tsFiles')")
|
@PreAuthorize("@el.check('add:tsFiles')")
|
||||||
public ResponseResult addTsFile(@RequestBody TsFiles tsFiles) {
|
public ResponseResult addTsFile(@RequestBody TsFiles tsFiles) throws IOException {
|
||||||
//对象不能为空
|
//对象不能为空
|
||||||
if (ObjUtil.isEmpty(tsFiles)) {
|
if (ObjUtil.isEmpty(tsFiles)) {
|
||||||
return ResponseResult.error("参数为空");
|
return ResponseResult.error("参数为空");
|
||||||
@ -461,4 +461,6 @@ public class TsFilesController {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -109,7 +109,7 @@ public interface ITsFilesService extends IService<TsFiles> {
|
|||||||
* TsFiles 文档内容
|
* TsFiles 文档内容
|
||||||
* 返回值说明: com.yfd.platform.config.ResponseResult 返回新增成功或者失败
|
* 返回值说明: com.yfd.platform.config.ResponseResult 返回新增成功或者失败
|
||||||
***********************************/
|
***********************************/
|
||||||
ResponseResult addTsFile(TsFiles tsFiles);
|
ResponseResult addTsFile(TsFiles tsFiles) throws IOException;
|
||||||
|
|
||||||
/**********************************
|
/**********************************
|
||||||
* 用途说明: 查询实验数据管理文件夹
|
* 用途说明: 查询实验数据管理文件夹
|
||||||
|
@ -5,6 +5,7 @@ import cn.hutool.core.collection.CollUtil;
|
|||||||
|
|
||||||
import java.nio.charset.StandardCharsets;
|
import java.nio.charset.StandardCharsets;
|
||||||
import java.nio.file.*;
|
import java.nio.file.*;
|
||||||
|
import java.nio.file.attribute.BasicFileAttributes;
|
||||||
import java.security.MessageDigest;
|
import java.security.MessageDigest;
|
||||||
import java.security.NoSuchAlgorithmException;
|
import java.security.NoSuchAlgorithmException;
|
||||||
import java.text.SimpleDateFormat;
|
import java.text.SimpleDateFormat;
|
||||||
@ -62,6 +63,7 @@ import org.apache.commons.compress.compressors.bzip2.BZip2CompressorOutputStream
|
|||||||
import org.apache.commons.compress.compressors.gzip.GzipCompressorInputStream;
|
import org.apache.commons.compress.compressors.gzip.GzipCompressorInputStream;
|
||||||
import org.apache.commons.compress.compressors.gzip.GzipCompressorOutputStream;
|
import org.apache.commons.compress.compressors.gzip.GzipCompressorOutputStream;
|
||||||
import org.apache.commons.compress.compressors.xz.XZCompressorOutputStream;
|
import org.apache.commons.compress.compressors.xz.XZCompressorOutputStream;
|
||||||
|
import org.apache.commons.io.FileUtils;
|
||||||
import org.apache.commons.io.FilenameUtils;
|
import org.apache.commons.io.FilenameUtils;
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
@ -75,10 +77,7 @@ import javax.xml.crypto.Data;
|
|||||||
import java.io.*;
|
import java.io.*;
|
||||||
import java.sql.Timestamp;
|
import java.sql.Timestamp;
|
||||||
import java.time.LocalDateTime;
|
import java.time.LocalDateTime;
|
||||||
import java.util.zip.GZIPInputStream;
|
import java.util.zip.*;
|
||||||
import java.util.zip.ZipEntry;
|
|
||||||
import java.util.zip.ZipFile;
|
|
||||||
import java.util.zip.ZipInputStream;
|
|
||||||
|
|
||||||
import org.apache.commons.codec.binary.Hex;
|
import org.apache.commons.codec.binary.Hex;
|
||||||
|
|
||||||
@ -472,8 +471,41 @@ public class TsFilesServiceImpl extends ServiceImpl<TsFilesMapper, TsFiles> impl
|
|||||||
***********************************/
|
***********************************/
|
||||||
@Override
|
@Override
|
||||||
@Transactional(rollbackFor = Exception.class)// 添加事务注解,遇到异常时回滚
|
@Transactional(rollbackFor = Exception.class)// 添加事务注解,遇到异常时回滚
|
||||||
public ResponseResult addTsFile(TsFiles tsFiles) {
|
public ResponseResult addTsFile(TsFiles tsFiles) throws IOException {
|
||||||
|
|
||||||
|
if (tsFiles.getIsFile().equals("FILE")) {
|
||||||
|
StorageSourceConfig config = storageSourceConfigMapper.selectOne(new QueryWrapper<StorageSourceConfig>().eq("name", "filePath"));
|
||||||
|
String basePath = config.getValue() + tsFiles.getWorkPath();
|
||||||
|
// 拼接完整文件路径
|
||||||
|
|
||||||
|
// 拼接完整的文件路径
|
||||||
|
Path filePath = Paths.get(basePath, tsFiles.getFileName() + ".txt");
|
||||||
|
|
||||||
|
// 确保目录存在,如果不存在则创建目录
|
||||||
|
Files.createDirectories(filePath.getParent());
|
||||||
|
|
||||||
|
// 使用 Files.write() 写入字符串内容
|
||||||
|
Files.write(filePath, "默认内容".getBytes(StandardCharsets.UTF_8));
|
||||||
|
tsFiles.setFileName(tsFiles.getFileName() + ".txt");
|
||||||
|
UsernamePasswordAuthenticationToken authentication =
|
||||||
|
(UsernamePasswordAuthenticationToken) SecurityContextHolder.getContext().getAuthentication();
|
||||||
|
LoginUser loginuser = (LoginUser) authentication.getPrincipal();
|
||||||
|
// 设置当前时间
|
||||||
|
LocalDateTime now = LocalDateTime.now();
|
||||||
|
// 转换为 Timestamp
|
||||||
|
Timestamp currentTime = Timestamp.valueOf(now);
|
||||||
|
tsFiles.setUploadTime(currentTime);
|
||||||
|
tsFiles.setUploader(loginuser.getUsername());
|
||||||
|
tsFiles.setFileSize("0");
|
||||||
|
int valueAdded = tsFilesMapper.insert(tsFiles);
|
||||||
|
if (valueAdded == 1) {
|
||||||
|
LOGGER.info("文件创建成功");
|
||||||
|
return ResponseResult.success();
|
||||||
|
} else {
|
||||||
|
LOGGER.error("文件创建失败");
|
||||||
|
return ResponseResult.error();
|
||||||
|
}
|
||||||
|
} else {
|
||||||
// 校验文件名是否包含非法字符
|
// 校验文件名是否包含非法字符
|
||||||
String fileName = tsFiles.getFileName();
|
String fileName = tsFiles.getFileName();
|
||||||
if (containsInvalidCharacters(fileName)) {
|
if (containsInvalidCharacters(fileName)) {
|
||||||
@ -547,6 +579,7 @@ public class TsFilesServiceImpl extends ServiceImpl<TsFilesMapper, TsFiles> impl
|
|||||||
return ResponseResult.error();
|
return ResponseResult.error();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// 校验文件名是否包含非法字符
|
// 校验文件名是否包含非法字符
|
||||||
private boolean containsInvalidCharacters(String fileName) {
|
private boolean containsInvalidCharacters(String fileName) {
|
||||||
@ -1018,13 +1051,11 @@ public class TsFilesServiceImpl extends ServiceImpl<TsFilesMapper, TsFiles> impl
|
|||||||
String zipFileName = compressedName + "." + compressedFormat;
|
String zipFileName = compressedName + "." + compressedFormat;
|
||||||
|
|
||||||
// 使用 try-with-resources 确保 zipOut 在使用后关闭
|
// 使用 try-with-resources 确保 zipOut 在使用后关闭
|
||||||
try (ZipArchiveOutputStream zipOut = new ZipArchiveOutputStream(new FileOutputStream(zipFilePath.toFile()))) {
|
|
||||||
// 设置压缩级别,可以选择调整
|
// 设置压缩级别,可以选择调整
|
||||||
zipOut.setLevel(ZipArchiveOutputStream.STORED); // 或者使用其他的压缩级别
|
// zipOut.setLevel(ZipArchiveOutputStream.STORED); // 或者使用其他的压缩级别
|
||||||
// 调用压缩方法
|
// 调用压缩方法
|
||||||
Boolean value = compressToSameDirectory(sourceDirs, compressedFormat);
|
Boolean value = compressToSameDirectory(sourceDirs, compressedFormat);
|
||||||
if (value) {
|
if (value) {
|
||||||
zipOut.finish(); // 确保所有数据都已写入
|
|
||||||
//表结构增加 nodeId, String TaskId
|
//表结构增加 nodeId, String TaskId
|
||||||
TsFiles tsFiles = new TsFiles();
|
TsFiles tsFiles = new TsFiles();
|
||||||
tsFiles.setTaskId(filesList.get(0).getTaskId());
|
tsFiles.setTaskId(filesList.get(0).getTaskId());
|
||||||
@ -1098,100 +1129,26 @@ public class TsFilesServiceImpl extends ServiceImpl<TsFilesMapper, TsFiles> impl
|
|||||||
} else {
|
} else {
|
||||||
returnResult = "压缩失败";
|
returnResult = "压缩失败";
|
||||||
}
|
}
|
||||||
} catch (IOException e) {
|
|
||||||
e.printStackTrace();
|
|
||||||
}
|
|
||||||
return returnResult;
|
return returnResult;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// ================== 核心方法改造 ==================
|
// ================== 核心方法改造 ==================
|
||||||
|
|
||||||
/**
|
|
||||||
* 多路径压缩到各自同级目录
|
private Boolean compressToSameDirectory(List<Path> sourcePaths, String compressedFormat) {
|
||||||
* @param sourcePaths 要压缩的路径集合
|
|
||||||
* @param compressionFormat 前端传入的压缩格式字符串
|
|
||||||
* @return 压缩成功返回true,失败返回false
|
|
||||||
*/
|
|
||||||
public boolean compressToSameDirectory(List<Path> sourcePaths, String compressionFormat) {
|
|
||||||
try {
|
try {
|
||||||
// 转换压缩格式
|
switch (compressedFormat.toUpperCase()) {
|
||||||
CompressionFormat format = CompressionFormat.fromString(compressionFormat);
|
case "ZIP":
|
||||||
|
return compressToZip(sourcePaths);
|
||||||
// 遍历所有路径进行压缩
|
case "TAR.GZ":
|
||||||
for (Path sourcePath : sourcePaths) {
|
return compressToTarGz(sourcePaths);
|
||||||
// 验证路径有效性
|
// case "7Z":
|
||||||
validatePath(sourcePath);
|
// return compressTo7z(sourcePaths);
|
||||||
|
default:
|
||||||
// 生成目标路径
|
throw new IllegalArgumentException("不支持的压缩格式: " + compressedFormat);
|
||||||
Path targetPath = generateTargetPath(sourcePath, format);
|
|
||||||
|
|
||||||
// 执行压缩
|
|
||||||
if (!compressSinglePath(sourcePath, targetPath, format)) {
|
|
||||||
return false; // 任一压缩失败则终止
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
return true; // 全部压缩成功
|
|
||||||
} catch (IllegalArgumentException e) {
|
|
||||||
System.err.println("格式错误: " + e.getMessage());
|
|
||||||
return false;
|
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
System.err.println("压缩失败: " + e.getMessage());
|
|
||||||
e.printStackTrace();
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// ================== 核心私有方法 ==================
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 验证路径有效性
|
|
||||||
* @param path 待验证路径
|
|
||||||
* @throws IOException 路径无效时抛出
|
|
||||||
*/
|
|
||||||
private void validatePath(Path path) throws IOException {
|
|
||||||
if (!Files.exists(path)) {
|
|
||||||
throw new FileNotFoundException("路径不存在: " + path);
|
|
||||||
}
|
|
||||||
if (!Files.isReadable(path)) {
|
|
||||||
throw new AccessDeniedException("无读取权限: " + path);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 生成目标压缩文件路径
|
|
||||||
* @param sourcePath 源路径
|
|
||||||
* @param format 压缩格式
|
|
||||||
* @return 目标路径(同级目录+格式后缀)
|
|
||||||
*/
|
|
||||||
private Path generateTargetPath(Path sourcePath, CompressionFormat format) {
|
|
||||||
// 获取无扩展名的文件名
|
|
||||||
String baseName = FilenameUtils.removeExtension(sourcePath.getFileName().toString());
|
|
||||||
// 添加压缩后缀
|
|
||||||
String fileName = baseName + "." + format.getPrimaryExtension();
|
|
||||||
return sourcePath.resolveSibling(fileName);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 单路径压缩核心方法
|
|
||||||
* @return 压缩成功返回true,失败返回false
|
|
||||||
*/
|
|
||||||
private boolean compressSinglePath(Path sourcePath, Path targetPath, CompressionFormat format) {
|
|
||||||
try {
|
|
||||||
switch (format) {
|
|
||||||
case ZIP:
|
|
||||||
compressToZip(sourcePath, targetPath);
|
|
||||||
break;
|
|
||||||
case TAR_GZ:
|
|
||||||
compressToTarGz(sourcePath, targetPath);
|
|
||||||
break;
|
|
||||||
case SEVEN_ZIP:
|
|
||||||
compressTo7z(sourcePath, targetPath);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
} catch (IOException e) {
|
|
||||||
System.err.println("压缩失败: " + sourcePath);
|
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@ -1199,222 +1156,252 @@ public class TsFilesServiceImpl extends ServiceImpl<TsFilesMapper, TsFiles> impl
|
|||||||
|
|
||||||
// ================== ZIP格式压缩实现 ==================
|
// ================== ZIP格式压缩实现 ==================
|
||||||
|
|
||||||
private void compressToZip(Path source, Path target) throws IOException {
|
|
||||||
try (ZipArchiveOutputStream zipOut = new ZipArchiveOutputStream(Files.newOutputStream(target))) {
|
/**
|
||||||
Set<Path> processedPaths = new HashSet<>();
|
* 压缩多个文件/目录到单个ZIP
|
||||||
processZipEntry(source, zipOut, "", processedPaths);
|
*/
|
||||||
}
|
public boolean compressToZip(List<Path> sourcePaths) {
|
||||||
|
if (sourcePaths.isEmpty()) {
|
||||||
|
LOGGER.warn("源路径列表为空,无法压缩");
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void processZipEntry(Path currentPath,
|
Path zipPath = generateZipPath(sourcePaths.get(0));
|
||||||
ZipArchiveOutputStream zipOut,
|
try (ZipOutputStream zipOut = new ZipOutputStream(Files.newOutputStream(zipPath))) {
|
||||||
String parentEntry,
|
zipOut.setLevel(Deflater.DEFAULT_COMPRESSION);
|
||||||
Set<Path> processedPaths) throws IOException {
|
|
||||||
// 获取相对于压缩根的路径
|
|
||||||
Path relativePath = getRelativePath(currentPath);
|
|
||||||
|
|
||||||
// 构建条目名称(关键修改)
|
for (Path sourcePath : sourcePaths) {
|
||||||
String entryName = buildZipEntryName(relativePath, parentEntry);
|
if (Files.isDirectory(sourcePath)) {
|
||||||
|
addDirectoryToZip(sourcePath, zipOut, sourcePath.getFileName().toString());
|
||||||
Path realPath = currentPath.toRealPath();
|
|
||||||
|
|
||||||
if (Files.isDirectory(currentPath)) {
|
|
||||||
if (processedPaths.contains(realPath)) return;
|
|
||||||
processedPaths.add(realPath);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (Files.isDirectory(currentPath)) {
|
|
||||||
handleZipDirectory(zipOut, entryName);
|
|
||||||
processZipChildren(currentPath, zipOut, entryName, processedPaths);
|
|
||||||
} else {
|
} else {
|
||||||
addFileToZip(currentPath, zipOut, entryName);
|
addFileToZip(sourcePath, zipOut, "");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// ================== TAR.GZ格式压缩实现 ==================
|
zipOut.finish();
|
||||||
|
return validateZip(zipPath);
|
||||||
private void compressToTarGz(Path source, Path target) throws IOException {
|
} catch (Exception e) {
|
||||||
try (TarArchiveOutputStream tarOut = new TarArchiveOutputStream(
|
LOGGER.error("压缩失败", e);
|
||||||
new GzipCompressorOutputStream(Files.newOutputStream(target)))) {
|
deleteQuietly(zipPath);
|
||||||
Set<Path> processedPaths = new HashSet<>();
|
return false;
|
||||||
processTarEntry(source, tarOut, "", processedPaths);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void addDirectoryToZip(Path dir, ZipOutputStream zipOut, String baseDir) throws IOException {
|
||||||
|
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();
|
||||||
|
return FileVisitResult.CONTINUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) throws IOException {
|
||||||
|
String entryName = baseDir + "/" + dir.relativize(file).toString().replace("\\", "/");
|
||||||
|
addFileEntry(file, entryName, zipOut);
|
||||||
|
return FileVisitResult.CONTINUE;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
private void addFileToZip(Path file, ZipOutputStream zipOut, String baseDir) throws IOException {
|
||||||
|
String entryName = baseDir + file.getFileName().toString();
|
||||||
|
addFileEntry(file, entryName, zipOut);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void addFileEntry(Path file, String entryName, ZipOutputStream zipOut) throws IOException {
|
||||||
|
LOGGER.debug("添加文件条目: {} (大小: {} 字节)", entryName, Files.size(file));
|
||||||
|
ZipEntry entry = new ZipEntry(entryName);
|
||||||
|
entry.setSize(Files.size(file));
|
||||||
|
entry.setTime(Files.getLastModifiedTime(file).toMillis());
|
||||||
|
zipOut.putNextEntry(entry);
|
||||||
|
|
||||||
|
try (InputStream input = Files.newInputStream(file)) {
|
||||||
|
byte[] buffer = new byte[8192];
|
||||||
|
int bytesRead;
|
||||||
|
while ((bytesRead = input.read(buffer)) != -1) {
|
||||||
|
zipOut.write(buffer, 0, bytesRead);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
zipOut.closeEntry();
|
||||||
|
}
|
||||||
|
|
||||||
|
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())) {
|
||||||
|
Enumeration<? extends ZipEntry> entries = zipFile.entries(); // 获取所有条目
|
||||||
|
if (!entries.hasMoreElements()) {
|
||||||
|
LOGGER.warn("ZIP 文件为空: {}", zipPath);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
while (entries.hasMoreElements()) {
|
||||||
|
ZipEntry entry = entries.nextElement();
|
||||||
|
try (InputStream is = zipFile.getInputStream(entry)) {
|
||||||
|
byte[] buffer = new byte[1024];
|
||||||
|
while (is.read(buffer) != -1) {} // 读取条目内容
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
LOGGER.info("ZIP 文件验证成功: {}", zipPath);
|
||||||
|
return true;
|
||||||
|
} catch (Exception e) {
|
||||||
|
LOGGER.error("ZIP 文件验证失败: {}", zipPath, e);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void deleteQuietly(Path path) {
|
||||||
|
try {
|
||||||
|
Files.deleteIfExists(path);
|
||||||
|
} catch (IOException ignored) {}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 获取相对于压缩根的路径
|
* 生成压缩文件路径(去除源文件扩展名)
|
||||||
*/
|
*/
|
||||||
private Path getRelativePath(Path absolutePath) {
|
private Path getCompressedFilePath(Path sourcePath, String extension) {
|
||||||
// 示例:如果压缩根是 /data/1.txt,则返回空路径
|
String fileName = sourcePath.getFileName().toString();
|
||||||
// 如果是压缩目录 /data/333,则返回相对路径
|
String baseName = fileName.contains(".")
|
||||||
// 需要根据实际压缩根路径调整实现
|
? fileName.substring(0, fileName.lastIndexOf('.'))
|
||||||
return absolutePath.getFileName();
|
: fileName;
|
||||||
|
return sourcePath.resolveSibling(baseName + "." + extension);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void processTarEntry(Path currentPath,
|
|
||||||
TarArchiveOutputStream tarOut,
|
|
||||||
String parentEntry,
|
|
||||||
Set<Path> processedPaths) throws IOException {
|
|
||||||
Path realPath = currentPath.toRealPath();
|
|
||||||
|
|
||||||
if (Files.isDirectory(currentPath)) {
|
|
||||||
if (processedPaths.contains(realPath)) return;
|
|
||||||
processedPaths.add(realPath);
|
|
||||||
}
|
|
||||||
|
|
||||||
String entryName = buildTarEntryName(currentPath, parentEntry);
|
|
||||||
TarArchiveEntry entry = new TarArchiveEntry(currentPath.toFile(), entryName);
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// ================== TAR.GZ格式压缩实现 ==================
|
||||||
|
private boolean compressToTarGz(List<Path> sourcePaths) throws IOException {
|
||||||
|
boolean success = true;
|
||||||
|
for (Path sourcePath : sourcePaths) {
|
||||||
|
Path tarGzPath = getCompressedFilePath(sourcePath, "tar.gz");
|
||||||
|
try (OutputStream fos = Files.newOutputStream(tarGzPath);
|
||||||
|
GzipCompressorOutputStream gzos = new GzipCompressorOutputStream(fos);
|
||||||
|
TarArchiveOutputStream tarOut = new TarArchiveOutputStream(gzos)) {
|
||||||
|
|
||||||
|
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);
|
tarOut.putArchiveEntry(entry);
|
||||||
tarOut.closeArchiveEntry();
|
|
||||||
|
|
||||||
if (Files.isDirectory(currentPath)) {
|
if (!isDir) {
|
||||||
try (DirectoryStream<Path> children = Files.newDirectoryStream(currentPath)) {
|
try (InputStream input = Files.newInputStream(filePath)) {
|
||||||
for (Path child : children) {
|
IOUtils.copy(input, tarOut);
|
||||||
processTarEntry(child, tarOut, entryName, processedPaths);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
tarOut.closeArchiveEntry();
|
||||||
|
});
|
||||||
|
|
||||||
|
tarOut.finish();
|
||||||
|
} catch (Exception e) {
|
||||||
|
success = false;
|
||||||
|
e.printStackTrace();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
return success;
|
||||||
|
}
|
||||||
|
|
||||||
// ================== 7Z格式压缩实现 ==================
|
// ================== 7Z格式压缩实现 ==================
|
||||||
|
// private boolean compressTo7z(List<Path> sourcePaths) throws IOException {
|
||||||
private void compressTo7z(Path source, Path target) throws IOException {
|
// boolean success = true;
|
||||||
try (SevenZOutputFile sevenZOut = new SevenZOutputFile(target.toFile())) {
|
// for (Path sourcePath : sourcePaths) {
|
||||||
Set<Path> processedPaths = new HashSet<>();
|
// Path sevenZPath = getCompressedFilePath(sourcePath, "7z");
|
||||||
process7zEntry(source, sevenZOut, "", processedPaths);
|
// try (SevenZOutputFile sevenZOutput = new SevenZOutputFile(sevenZPath.toFile())) {
|
||||||
}
|
//
|
||||||
}
|
// processEntries(sourcePath, (entryName, isDir) -> {
|
||||||
|
// SevenZArchiveEntry entry = sevenZOutput.createEntry();
|
||||||
private void process7zEntry(Path currentPath,
|
// entry.setName(entryName);
|
||||||
SevenZOutputFile sevenZOut,
|
// entry.setDirectory(isDir);
|
||||||
String parentEntry,
|
//
|
||||||
Set<Path> processedPaths) throws IOException {
|
// if (!isDir) {
|
||||||
Path realPath = currentPath.toRealPath();
|
// Path filePath = sourcePath.resolve(entryName);
|
||||||
|
// entry.setSize(Files.size(filePath));
|
||||||
if (Files.isDirectory(currentPath)) {
|
// sevenZOutput.putArchiveEntry(entry);
|
||||||
if (processedPaths.contains(realPath)) return;
|
//
|
||||||
processedPaths.add(realPath);
|
// try (InputStream input = Files.newInputStream(filePath)) {
|
||||||
}
|
// byte[] buffer = new byte[8192];
|
||||||
|
// int len;
|
||||||
String entryName = build7zEntryName(currentPath, parentEntry);
|
// while ((len = input.read(buffer)) != -1) {
|
||||||
SevenZArchiveEntry entry = sevenZOut.createArchiveEntry(currentPath.toFile(), entryName);
|
// sevenZOutput.write(buffer, 0, len);
|
||||||
sevenZOut.putArchiveEntry(entry);
|
// }
|
||||||
sevenZOut.closeArchiveEntry();
|
// }
|
||||||
|
//
|
||||||
if (Files.isDirectory(currentPath)) {
|
// sevenZOutput.closeArchiveEntry();
|
||||||
try (DirectoryStream<Path> children = Files.newDirectoryStream(currentPath)) {
|
// }
|
||||||
for (Path child : children) {
|
// });
|
||||||
process7zEntry(child, sevenZOut, entryName, processedPaths);
|
//
|
||||||
}
|
// } catch (Exception e) {
|
||||||
}
|
// success = false;
|
||||||
}
|
// e.printStackTrace();
|
||||||
}
|
// }
|
||||||
|
// }
|
||||||
|
// return success;
|
||||||
|
// }
|
||||||
|
|
||||||
// ================== 通用工具方法 ==================
|
// ================== 通用工具方法 ==================
|
||||||
|
private interface EntryProcessor {
|
||||||
private String buildZipEntryName(Path path, String parentEntry) {
|
void process(String entryName, boolean isDir) throws IOException;
|
||||||
// 仅保留文件名部分
|
|
||||||
String fileName = path.getFileName().toString();
|
|
||||||
|
|
||||||
// 根条目处理
|
|
||||||
if (parentEntry.isEmpty()) {
|
|
||||||
return Files.isDirectory(path) ? fileName + "/" : fileName;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// 子条目处理
|
private void processEntries(Path rootPath, EntryProcessor processor) throws IOException {
|
||||||
return parentEntry + (parentEntry.endsWith("/") ? "" : "/") + fileName
|
Files.walkFileTree(rootPath, new SimpleFileVisitor<Path>() {
|
||||||
+ (Files.isDirectory(path) ? "/" : "");
|
@Override
|
||||||
|
public FileVisitResult preVisitDirectory(Path dir, BasicFileAttributes attrs) throws IOException {
|
||||||
|
String entryName = rootPath.relativize(dir).toString().replace("\\", "/");
|
||||||
|
if (!entryName.isEmpty()) {
|
||||||
|
processor.process(entryName + "/", true);
|
||||||
|
}
|
||||||
|
return FileVisitResult.CONTINUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
private String buildTarEntryName(Path path, String parentEntry) {
|
@Override
|
||||||
return parentEntry.isEmpty() ?
|
public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) throws IOException {
|
||||||
path.getFileName().toString() :
|
String entryName = rootPath.relativize(file).toString().replace("\\", "/");
|
||||||
parentEntry + "/" + path.getFileName();
|
processor.process(entryName, false);
|
||||||
|
return FileVisitResult.CONTINUE;
|
||||||
|
}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
private String build7zEntryName(Path path, String parentEntry) {
|
|
||||||
return buildTarEntryName(path, parentEntry);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void handleZipDirectory(ZipArchiveOutputStream zipOut, String entryName)
|
// ================== ZIP条目添加方法 ==================
|
||||||
throws IOException {
|
private void addZipDirectoryEntry(ZipArchiveOutputStream zipOut, String entryName) throws IOException {
|
||||||
ZipArchiveEntry entry = new ZipArchiveEntry(entryName);
|
ZipArchiveEntry entry = new ZipArchiveEntry(entryName);
|
||||||
entry.setMethod(ZipEntry.STORED);
|
|
||||||
entry.setSize(0);
|
|
||||||
entry.setCrc(0);
|
|
||||||
zipOut.putArchiveEntry(entry);
|
zipOut.putArchiveEntry(entry);
|
||||||
zipOut.closeArchiveEntry();
|
zipOut.closeArchiveEntry();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void processZipChildren(Path dir,
|
private void addZipFileEntry(ZipArchiveOutputStream zipOut, Path filePath, String entryName) throws IOException {
|
||||||
ZipArchiveOutputStream zipOut,
|
ZipArchiveEntry entry = new ZipArchiveEntry(filePath.toFile(), entryName);
|
||||||
String parentEntry,
|
entry.setSize(Files.size(filePath));
|
||||||
Set<Path> processedPaths) throws IOException {
|
entry.setTime(Files.getLastModifiedTime(filePath).toMillis());
|
||||||
try (DirectoryStream<Path> children = Files.newDirectoryStream(dir)) {
|
|
||||||
for (Path child : children) {
|
|
||||||
processZipEntry(child, zipOut, parentEntry, processedPaths);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void addFileToZip(Path file, ZipArchiveOutputStream zipOut, String entryName)
|
|
||||||
throws IOException {
|
|
||||||
ZipArchiveEntry entry = new ZipArchiveEntry(entryName);
|
|
||||||
entry.setMethod(ZipEntry.DEFLATED);
|
|
||||||
entry.setSize(Files.size(file));
|
|
||||||
entry.setTime(Files.getLastModifiedTime(file).toMillis());
|
|
||||||
|
|
||||||
zipOut.putArchiveEntry(entry);
|
zipOut.putArchiveEntry(entry);
|
||||||
try (InputStream input = Files.newInputStream(file)) {
|
try (InputStream input = Files.newInputStream(filePath)) {
|
||||||
IOUtils.copy(input, zipOut);
|
IOUtils.copy(input, zipOut);
|
||||||
}
|
}
|
||||||
zipOut.closeArchiveEntry();
|
zipOut.closeArchiveEntry();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*************************************解压缩*******************************************/
|
/*************************************解压缩*******************************************/
|
||||||
|
|
||||||
/**********************************
|
/**********************************
|
||||||
@ -1442,8 +1429,12 @@ public class TsFilesServiceImpl extends ServiceImpl<TsFilesMapper, TsFiles> impl
|
|||||||
// // 4. 构建解压目标路径
|
// // 4. 构建解压目标路径
|
||||||
Path destRoot;
|
Path destRoot;
|
||||||
if (hasFolder) {
|
if (hasFolder) {
|
||||||
|
// 动态去掉 .zip 后缀(仅用于路径构建)
|
||||||
|
String folderName = zipName.toLowerCase().endsWith(".zip")
|
||||||
|
? zipName.substring(0, zipName.length() - 4)
|
||||||
|
: zipName;
|
||||||
// 如果有文件夹,创建子目录(如 E:/yun/333/222/)
|
// 如果有文件夹,创建子目录(如 E:/yun/333/222/)
|
||||||
destRoot = Paths.get(storageSourceConfig.getValue(), decompressionPath, zipName);
|
destRoot = Paths.get(storageSourceConfig.getValue(), decompressionPath, folderName);
|
||||||
} else {
|
} else {
|
||||||
// 如果只有文件,直接解压到目标目录(如 E:/yun/333/)
|
// 如果只有文件,直接解压到目标目录(如 E:/yun/333/)
|
||||||
destRoot = Paths.get(storageSourceConfig.getValue(), decompressionPath);
|
destRoot = Paths.get(storageSourceConfig.getValue(), decompressionPath);
|
||||||
@ -1655,17 +1646,6 @@ public class TsFilesServiceImpl extends ServiceImpl<TsFilesMapper, TsFiles> impl
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// 新增:统一解压入口方法(保持原有逻辑结构)
|
// 新增:统一解压入口方法(保持原有逻辑结构)
|
||||||
private File unzipToTemp(Path zipFilePath, String baseDir) throws IOException {
|
private File unzipToTemp(Path zipFilePath, String baseDir) throws IOException {
|
||||||
String fileName = zipFilePath.getFileName().toString();
|
String fileName = zipFilePath.getFileName().toString();
|
||||||
@ -1700,7 +1680,6 @@ public class TsFilesServiceImpl extends ServiceImpl<TsFilesMapper, TsFiles> impl
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// 保持原有ZIP判断方法不变
|
// 保持原有ZIP判断方法不变
|
||||||
private boolean hasFolderInZip(Path zipFilePath) throws IOException {
|
private boolean hasFolderInZip(Path zipFilePath) throws IOException {
|
||||||
try (ZipFile zipFile = new ZipFile(zipFilePath.toFile())) {
|
try (ZipFile zipFile = new ZipFile(zipFilePath.toFile())) {
|
||||||
@ -1738,80 +1717,68 @@ public class TsFilesServiceImpl extends ServiceImpl<TsFilesMapper, TsFiles> impl
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// 保持原有解压逻辑结构的ZIP实现
|
// 保持原有解压逻辑结构的ZIP实现
|
||||||
// 修改后的ZIP解压方法(修复解压问题)
|
// 修改后的ZIP解压方法(修复解压问题)
|
||||||
private File unzipFile(Path sourcePath, String baseDir) throws IOException {
|
private File unzipFile(Path sourcePath, String baseDir) throws IOException {
|
||||||
|
// 创建目标目录
|
||||||
Path destRoot = Paths.get(baseDir);
|
Path destRoot = Paths.get(baseDir);
|
||||||
Files.createDirectories(destRoot);
|
Files.createDirectories(destRoot);
|
||||||
|
|
||||||
// 关键修复1:使用与压缩时相同的字符集
|
|
||||||
try (ZipInputStream zis = new ZipInputStream(
|
try (ZipInputStream zis = new ZipInputStream(
|
||||||
Files.newInputStream(sourcePath),
|
Files.newInputStream(sourcePath), StandardCharsets.UTF_8)) {
|
||||||
StandardCharsets.UTF_8)) {
|
|
||||||
|
|
||||||
// 关键修复2:记录已处理路径防止重复
|
|
||||||
Set<String> processedEntries = new HashSet<>();
|
|
||||||
|
|
||||||
ZipEntry entry;
|
ZipEntry entry;
|
||||||
while ((entry = zis.getNextEntry()) != null) {
|
while ((entry = zis.getNextEntry()) != null) {
|
||||||
String entryName = entry.getName();
|
try {
|
||||||
|
// 跳过 macOS 系统文件
|
||||||
// 过滤系统文件(与压缩时逻辑对应)
|
if (entry.getName().startsWith("__MACOSX")) {
|
||||||
if (entryName.startsWith("__MACOSX/")) {
|
|
||||||
zis.closeEntry();
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
// 关键修复3:路径标准化处理
|
// 标准化路径并处理目录标识
|
||||||
entryName = entryName.replace("\\", "/"); // 统一分隔符
|
String entryName = entry.getName()
|
||||||
if (processedEntries.contains(entryName)) {
|
.replace("\\", "/")
|
||||||
|
.replaceFirst("^/+", ""); // 去除开头的斜杠
|
||||||
|
|
||||||
|
// 检测是否为目录(兼容以'/'结尾的条目)
|
||||||
|
boolean isDirectory = entry.isDirectory() || entry.getName().endsWith("/");
|
||||||
|
|
||||||
|
// 调整路径:去除顶层目录(假设所有文件在单一顶层目录下)
|
||||||
|
if (entryName.contains("/")) {
|
||||||
|
int firstSlash = entryName.indexOf('/');
|
||||||
|
entryName = entryName.substring(firstSlash + 1);
|
||||||
|
|
||||||
|
// 若处理后名称为空,则跳过顶层目录条目
|
||||||
|
if (entryName.isEmpty() && isDirectory) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
processedEntries.add(entryName);
|
|
||||||
|
|
||||||
// 构建目标路径
|
|
||||||
Path destPath = destRoot.resolve(entryName).normalize();
|
|
||||||
validatePathSafetya(destPath, destRoot);
|
|
||||||
|
|
||||||
// 日志跟踪
|
|
||||||
LOGGER.debug("[解压] 处理条目:{} → {}", entryName, destPath);
|
|
||||||
|
|
||||||
if (entry.isDirectory()) {
|
|
||||||
Files.createDirectories(destPath);
|
|
||||||
LOGGER.debug("创建目录:{}", destPath);
|
|
||||||
} else {
|
|
||||||
// 关键修复4:确保父目录存在
|
|
||||||
Path parentDir = destPath.getParent();
|
|
||||||
if (!Files.exists(parentDir)) {
|
|
||||||
Files.createDirectories(parentDir);
|
|
||||||
LOGGER.debug("创建父目录:{}", parentDir);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// 关键修复5:使用与压缩时相同的写入方式
|
Path targetPath = destRoot.resolve(entryName).normalize();
|
||||||
try (BufferedOutputStream bos = new BufferedOutputStream(
|
validatePathSafetya(targetPath, destRoot);
|
||||||
Files.newOutputStream(destPath,
|
|
||||||
StandardOpenOption.CREATE,
|
|
||||||
StandardOpenOption.TRUNCATE_EXISTING))) {
|
|
||||||
|
|
||||||
byte[] buffer = new byte[8192];
|
// 处理目录
|
||||||
int len;
|
if (isDirectory) {
|
||||||
while ((len = zis.read(buffer)) > 0) {
|
Files.createDirectories(targetPath);
|
||||||
bos.write(buffer, 0, len);
|
|
||||||
}
|
}
|
||||||
// 立即刷新到磁盘
|
// 处理文件
|
||||||
bos.flush();
|
else {
|
||||||
LOGGER.info("已解压文件:{} (大小:{} bytes)",
|
if (Files.exists(targetPath)) {
|
||||||
destPath, Files.size(destPath));
|
LOGGER.warn("文件已存在,跳过覆盖: {}", targetPath);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
// 确保父目录存在
|
||||||
|
Files.createDirectories(targetPath.getParent());
|
||||||
|
try (OutputStream os = Files.newOutputStream(targetPath)) {
|
||||||
|
IOUtils.copy(zis, os);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
zis.closeEntry();
|
} finally {
|
||||||
|
zis.closeEntry(); // 确保每个条目只关闭一次
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 最终验证
|
|
||||||
LOGGER.info("解压完成,验证文件结构:");
|
|
||||||
Files.walk(destRoot)
|
|
||||||
.forEach(path -> LOGGER.info("-> {}", path));
|
|
||||||
|
|
||||||
return destRoot.toFile();
|
return destRoot.toFile();
|
||||||
}
|
}
|
||||||
@ -1828,45 +1795,6 @@ public class TsFilesServiceImpl extends ServiceImpl<TsFilesMapper, TsFiles> impl
|
|||||||
+ " 超出根目录 " + normalizedDest);
|
+ " 超出根目录 " + normalizedDest);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
/**
|
|
||||||
* 安全写入文件(带缓冲)
|
|
||||||
*/
|
|
||||||
private void writeFile(ZipInputStream zis, Path destPath) throws IOException {
|
|
||||||
try (BufferedOutputStream bos = new BufferedOutputStream(
|
|
||||||
Files.newOutputStream(destPath,
|
|
||||||
StandardOpenOption.CREATE,
|
|
||||||
StandardOpenOption.TRUNCATE_EXISTING
|
|
||||||
)
|
|
||||||
)) {
|
|
||||||
byte[] buffer = new byte[8192];
|
|
||||||
int len;
|
|
||||||
while ((len = zis.read(buffer)) > 0) {
|
|
||||||
bos.write(buffer, 0, len);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 内部类:存储 ZIP 条目信息
|
|
||||||
*/
|
|
||||||
private static class ZipEntryInfo {
|
|
||||||
private final String name;
|
|
||||||
private final boolean isDirectory;
|
|
||||||
|
|
||||||
public ZipEntryInfo(String name, boolean isDirectory) {
|
|
||||||
this.name = name;
|
|
||||||
this.isDirectory = isDirectory;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getName() {
|
|
||||||
return name;
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean isDirectory() {
|
|
||||||
return isDirectory;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// 新增:TAR.GZ解压实现(保持相同路径逻辑)
|
// 新增:TAR.GZ解压实现(保持相同路径逻辑)
|
||||||
@ -1935,36 +1863,6 @@ public class TsFilesServiceImpl extends ServiceImpl<TsFilesMapper, TsFiles> impl
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// /**
|
// /**
|
||||||
// * 解析压缩包条目(支持多种格式)
|
// * 解析压缩包条目(支持多种格式)
|
||||||
// */
|
// */
|
||||||
@ -2015,8 +1913,6 @@ public class TsFilesServiceImpl extends ServiceImpl<TsFilesMapper, TsFiles> impl
|
|||||||
// }
|
// }
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
//上面这个方法会覆盖 TODO
|
//上面这个方法会覆盖 TODO
|
||||||
// private File unzipToTemp(Path zipFilePath, String baseDir) throws IOException {
|
// private File unzipToTemp(Path zipFilePath, String baseDir) throws IOException {
|
||||||
// // 1. 直接构建目标路径(baseDir/zipName)
|
// // 1. 直接构建目标路径(baseDir/zipName)
|
||||||
@ -3835,7 +3731,7 @@ public class TsFilesServiceImpl extends ServiceImpl<TsFilesMapper, TsFiles> impl
|
|||||||
dto.setUrl(null);
|
dto.setUrl(null);
|
||||||
dto.setType(null);
|
dto.setType(null);
|
||||||
|
|
||||||
}else{
|
} else {
|
||||||
dto.setUrl(fileItemResult.getUrl());
|
dto.setUrl(fileItemResult.getUrl());
|
||||||
//如果是压缩文件 类型就给zip
|
//如果是压缩文件 类型就给zip
|
||||||
boolean isValid = hasValidExtension(fileItemResult.getName(), sysDictionaryItems);
|
boolean isValid = hasValidExtension(fileItemResult.getName(), sysDictionaryItems);
|
||||||
@ -3931,8 +3827,6 @@ public class TsFilesServiceImpl extends ServiceImpl<TsFilesMapper, TsFiles> impl
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// 封装发送数据的逻辑
|
// 封装发送数据的逻辑
|
||||||
private void sendData(String token, String[] values, int lineCount) {
|
private void sendData(String token, String[] values, int lineCount) {
|
||||||
if (Thread.currentThread().isInterrupted()) {
|
if (Thread.currentThread().isInterrupted()) {
|
||||||
@ -3980,7 +3874,7 @@ public class TsFilesServiceImpl extends ServiceImpl<TsFilesMapper, TsFiles> impl
|
|||||||
StorageSourceConfig config = storageSourceConfigMapper.selectOne(new QueryWrapper<StorageSourceConfig>().eq("name", "filePath"));
|
StorageSourceConfig config = storageSourceConfigMapper.selectOne(new QueryWrapper<StorageSourceConfig>().eq("name", "filePath"));
|
||||||
TsFiles tsFiles = tsFilesMapper.selectById(id);
|
TsFiles tsFiles = tsFilesMapper.selectById(id);
|
||||||
// 1. 路径标准化与安全校验
|
// 1. 路径标准化与安全校验
|
||||||
Path targetPath = validateAndNormalizePath(config.getValue()+tsFiles.getWorkPath()+tsFiles.getFileName());
|
Path targetPath = validateAndNormalizePath(config.getValue() + tsFiles.getWorkPath() + tsFiles.getFileName());
|
||||||
|
|
||||||
StringBuilder content = new StringBuilder();
|
StringBuilder content = new StringBuilder();
|
||||||
|
|
||||||
@ -3995,7 +3889,6 @@ public class TsFilesServiceImpl extends ServiceImpl<TsFilesMapper, TsFiles> impl
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 验证路径是否合法并转换为标准化路径
|
* 验证路径是否合法并转换为标准化路径
|
||||||
*/
|
*/
|
||||||
@ -4029,7 +3922,7 @@ public class TsFilesServiceImpl extends ServiceImpl<TsFilesMapper, TsFiles> impl
|
|||||||
StorageSourceConfig config = storageSourceConfigMapper.selectOne(new QueryWrapper<StorageSourceConfig>().eq("name", "filePath"));
|
StorageSourceConfig config = storageSourceConfigMapper.selectOne(new QueryWrapper<StorageSourceConfig>().eq("name", "filePath"));
|
||||||
TsFiles tsFiles = tsFilesMapper.selectById(id);
|
TsFiles tsFiles = tsFilesMapper.selectById(id);
|
||||||
// 1. 路径标准化与安全校验
|
// 1. 路径标准化与安全校验
|
||||||
Path targetPath = validateAndNormalizePath(config.getValue()+tsFiles.getWorkPath()+tsFiles.getFileName());
|
Path targetPath = validateAndNormalizePath(config.getValue() + tsFiles.getWorkPath() + tsFiles.getFileName());
|
||||||
// 2. 确保父目录存在
|
// 2. 确保父目录存在
|
||||||
Path parentDir = targetPath.getParent();
|
Path parentDir = targetPath.getParent();
|
||||||
if (parentDir != null && !Files.exists(parentDir)) {
|
if (parentDir != null && !Files.exists(parentDir)) {
|
||||||
|
Loading…
Reference in New Issue
Block a user