提交代码

This commit is contained in:
lilin 2025-04-01 18:13:08 +08:00
parent 2939613be8
commit 0499b55011
3 changed files with 108 additions and 8 deletions

View File

@ -375,6 +375,26 @@ public class TsFilesController {
} }
/**********************************
* 用途说明: 查询本地和备份空间结构树
* 参数说明 taskId 节点ID
* 参数说明 nodeId 任务ID
* 返回值说明: com.yfd.platform.config.ResponseResult 返回双树数据
***********************************/
@Log(module = "实验数据管理", value = "查询本地和备份空间结构树!")
@PostMapping("/listLocalAndBackup")
@ApiOperation("查询本地和备份空间结构树")
public ResponseResult listLocalAndBackup(String taskId, String nodeId) {
if (StrUtil.isBlank(taskId) && StrUtil.isBlank(nodeId)) {
return ResponseResult.error("参数为空");
}
//查询本地树和minio树
DualTreeResponse response = tsFilesService.listLocalAndBackup(taskId, nodeId);
return ResponseResult.successData(response);
}
/********************************** /**********************************
* 用途说明: 查询本地结构树 * 用途说明: 查询本地结构树

View File

@ -207,4 +207,12 @@ public interface ITsFilesService extends IService<TsFiles> {
* 返回值说明: com.yfd.platform.config.ResponseResult 返回双树数据 * 返回值说明: com.yfd.platform.config.ResponseResult 返回双树数据
***********************************/ ***********************************/
DualTreeResponse listBackupTree(String taskId, String nodeId, String id); DualTreeResponse listBackupTree(String taskId, String nodeId, String id);
/**********************************
* 用途说明: 查询本地和备份空间结构树
* 参数说明 taskId 节点ID
* 参数说明 nodeId 任务ID
* 返回值说明: com.yfd.platform.config.ResponseResult 返回双树数据
***********************************/
DualTreeResponse listLocalAndBackup(String taskId, String nodeId);
} }

View File

@ -2234,24 +2234,43 @@ public class TsFilesServiceImpl extends ServiceImpl<TsFilesMapper, TsFiles> impl
} }
} }
// 保留Unix权限 // 保留Unix权限仅在非Windows系统生效
if (!System.getProperty("os.name").toLowerCase().contains("win")) { if (!System.getProperty("os.name").toLowerCase().contains("win")) {
Files.setPosixFilePermissions(targetPath, try {
PosixFilePermissions.fromString(getPosixMode(entry.getMode()))); Files.setPosixFilePermissions(
targetPath,
PosixFilePermissions.fromString(getPosixMode(entry.getMode()))
);
} catch (IllegalArgumentException e) {
// 捕获非法权限格式异常避免进程终止
System.err.println("警告: 无法设置权限 [" + entry.getMode() + "] 文件: " + targetPath);
}
} }
} }
} }
return destRoot.toFile(); return destRoot.toFile();
} }
// 转换Unix权限位 /**
* 将TAR文件条目的权限位转换为POSIX格式字符串
* (修正1移除空格修正2屏蔽高位)
*/
private String getPosixMode(int mode) { private String getPosixMode(int mode) {
// 仅保留低9位权限信息用户//其他
mode &= 0777;
return String.format("%s%s%s%s%s%s%s%s%s", 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 & 0400) != 0 ? "r" : "-", // 用户读
(mode & 0040) != 0 ? "r" : "-", (mode & 0020) != 0 ? "w" : "-", (mode & 0010) != 0 ? "x" : "-", (mode & 0200) != 0 ? "w" : "-", // 用户写
(mode & 0004) != 0 ? "r" : "-", (mode & 0002) != 0 ? "w" : "-", (mode & 0001) != 0 ? "x" : "-"); (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" : "-"); // 其他执行
} }
/** /**
* 验证目标路径安全性防止路径穿越攻击 * 验证目标路径安全性防止路径穿越攻击
*/ */
@ -4284,6 +4303,59 @@ public class TsFilesServiceImpl extends ServiceImpl<TsFilesMapper, TsFiles> impl
// return new DualTreeResponse(localTrees, minioTrees); // return new DualTreeResponse(localTrees, minioTrees);
// } // }
/**********************************
* 用途说明: 查询本地和备份空间结构树
* 参数说明 taskId 节点ID
* 参数说明 nodeId 任务ID
* 返回值说明: com.yfd.platform.config.ResponseResult 返回双树数据
***********************************/
@Override
public DualTreeResponse listLocalAndBackup(String taskId, String nodeId) {
// 记录方法入参
LOGGER.info("Starting to build dual trees for taskId={}, nodeId={}", taskId, nodeId);
// 1. 批量查询所有相关节点
QueryWrapper<TsFiles> queryWrapper = new QueryWrapper<>();
queryWrapper.eq("task_id", taskId)
.eq("node_id", nodeId);
List<TsFiles> allNodes = tsFilesMapper.selectList(queryWrapper);
// 2. 构建内存索引提升查询效率
Map<String, List<TsFiles>> parentChildrenMap = allNodes.stream()
.collect(Collectors.groupingBy(TsFiles::getParentId));
LOGGER.debug("使用{}个条目构建父子映射", parentChildrenMap.size());
// 3. 双树构建容器
List<TreeDTO> localTrees = new ArrayList<>();
List<TreeDTO> minioTrees = new ArrayList<>();
// 4. 从顶级节点parentId为00开始构建树
List<TsFiles> rootNodes = parentChildrenMap.get("00");
if (rootNodes == null || rootNodes.isEmpty()) {
LOGGER.warn("找不到的根节点 taskId={}, nodeId={}", taskId, nodeId);
return new DualTreeResponse(localTrees, minioTrees);
}
if (rootNodes != null) {
for (TsFiles rootNode : rootNodes) {
// 构建本地树
TreeDTO localTree = buildTree(rootNode, parentChildrenMap, true);
if (localTree != null) {
localTrees.add(localTree);
LOGGER.debug("添加了本地树节点: {}", localTree.getId());
}
// 构建Minio树
TreeDTO minioTree = buildTree(rootNode, parentChildrenMap, false);
if (minioTree != null) {
minioTrees.add(minioTree);
LOGGER.debug("添加了MINIO树节点: {}", minioTree.getId());
}
}
}
LOGGER.info("Tree construction completed. Local nodes: {}, MinIO nodes: {}", localTrees.size(), minioTrees.size());
return new DualTreeResponse(localTrees, minioTrees);
}
/** /**
* 递归构建树形结构内存操作不再查询数据库 * 递归构建树形结构内存操作不再查询数据库
* *