提交代码

This commit is contained in:
lilin 2025-04-01 17:22:26 +08:00
parent a86bd18f4f
commit 2939613be8
7 changed files with 682 additions and 293 deletions

View File

@ -377,23 +377,58 @@ public class TsFilesController {
/********************************** /**********************************
* 用途说明: 查询本地和备份空间结构树 * 用途说明: 查询本地结构树
* 参数说明 taskId 节点ID * 参数说明 taskId 节点ID
* 参数说明 nodeId 任务ID * 参数说明 nodeId 任务ID
* 参数说明 id 文件夹ID
* 返回值说明: com.yfd.platform.config.ResponseResult 返回双树数据 * 返回值说明: com.yfd.platform.config.ResponseResult 返回双树数据
***********************************/ ***********************************/
@Log(module = "实验数据管理", value = "查询本地和备份空间结构树!") @Log(module = "实验数据管理", value = "查询本地结构树!")
@PostMapping("/listLocalAndBackup") @PostMapping("/listLocalTree")
@ApiOperation("查询本地和备份空间结构树") @ApiOperation("查询本地结构树")
public ResponseResult listLocalAndBackup(String taskId, String nodeId) { public ResponseResult listLocalTree(String taskId, String nodeId,String id) {
//查询本地树和minio树
DualTreeResponse response = tsFilesService.listLocalTree(taskId, nodeId,id);
return ResponseResult.successData(response);
}
if (StrUtil.isBlank(taskId) && StrUtil.isBlank(nodeId)) { /**********************************
* 用途说明: 查询备份空间结构树
* 参数说明 taskId 节点ID
* 参数说明 nodeId 任务ID
* 参数说明 id 文件夹ID
* 返回值说明: com.yfd.platform.config.ResponseResult 返回双树数据
***********************************/
@Log(module = "实验数据管理", value = "查询备份空间结构树!")
@PostMapping("/listBackupTree")
@ApiOperation("查询备份空间结构树")
public ResponseResult listBackupTree(String taskId, String nodeId,String id) {
//查询本地树和minio树
DualTreeResponse response = tsFilesService.listBackupTree(taskId, nodeId,id);
return ResponseResult.successData(response);
}
/**********************************
* 用途说明: 文件自动备份
* 参数说明 taskId 节点ID
* 参数说明 nodeId 任务ID
* 返回值说明: com.yfd.platform.config.ResponseResult 返回成功或者失败
***********************************/
@Log(module = "实验数据管理", value = "文件自动备份!")
@PostMapping("/automaticFileBackup")
@ApiOperation("自动备份本地文件到备份空间")
public ResponseResult automaticFileBackup(String taskId, String nodeId) {
if (StrUtil.isEmpty(taskId) || StrUtil.isEmpty(nodeId)) {
return ResponseResult.error("参数为空"); return ResponseResult.error("参数为空");
} }
//查询本地树和minio树 return ResponseResult.success(tsFilesService.automaticFileBackup(taskId,nodeId));
DualTreeResponse response = tsFilesService.listLocalAndBackup(taskId, nodeId);
return ResponseResult.successData(response);
} }
@ -430,6 +465,7 @@ public class TsFilesController {
/********************************** /**********************************
* 用途说明: 查询文件内容接口 * 用途说明: 查询文件内容接口
* 参数说明 id 文件的ID * 参数说明 id 文件的ID
* 参数说明 type 查看本地还是minio local minio
* 返回值说明: com.yfd.platform.config.ResponseResult文件内容的纯文本UTF-8 编码 * 返回值说明: com.yfd.platform.config.ResponseResult文件内容的纯文本UTF-8 编码
***********************************/ ***********************************/
@Log(module = "实验数据管理", value = "查询文件内容!") @Log(module = "实验数据管理", value = "查询文件内容!")
@ -437,7 +473,7 @@ public class TsFilesController {
@ApiOperation("查询文件内容") @ApiOperation("查询文件内容")
public ResponseResult getFileContent(@RequestParam String id) { public ResponseResult getFileContent(@RequestParam String id) {
try { try {
if (StrUtil.isBlank(id)) { if (StrUtil.isBlank(id) ) {
return ResponseResult.error("参数为空"); return ResponseResult.error("参数为空");
} }
String content = tsFilesService.readFileContent(id); String content = tsFilesService.readFileContent(id);

View File

@ -101,4 +101,7 @@ public class TreeDTO {
// 子节点列表 // 子节点列表
// 初始化 children 为一个空列表 // 初始化 children 为一个空列表
private List<TreeDTO> children = new ArrayList<>(); private List<TreeDTO> children = new ArrayList<>();
@TableField(exist = false)
private int number;
} }

View File

@ -140,13 +140,14 @@ public interface ITsFilesService extends IService<TsFiles> {
*/ */
String copyFileFolder(MoveCopyFileFolderRequest request)throws IOException; String copyFileFolder(MoveCopyFileFolderRequest request)throws IOException;
/********************************** // /**********************************
* 用途说明: 查询本地和备份空间结构树 // * 用途说明: 查询本地和备份空间结构树
* 参数说明 taskId 节点ID // * 参数说明 taskId 节点ID
* 参数说明 nodeId 任务ID // * 参数说明 nodeId 任务ID
* 返回值说明: com.yfd.platform.config.ResponseResult 返回双树数据 // * 参数说明 id 文件夹ID
***********************************/ // * 返回值说明: com.yfd.platform.config.ResponseResult 返回双树数据
DualTreeResponse listLocalAndBackup(String taskId, String nodeId); // ***********************************/
// DualTreeResponse listLocalAndBackup(String taskId, String nodeId,String id);
/** /**
@ -181,4 +182,29 @@ public interface ITsFilesService extends IService<TsFiles> {
* 返回值说明: com.yfd.platform.config.ResponseResult操作结果 * 返回值说明: com.yfd.platform.config.ResponseResult操作结果
***********************************/ ***********************************/
void batchUpdateFile(String id, List<ModifyCommand> modifications) throws IOException; void batchUpdateFile(String id, List<ModifyCommand> modifications) throws IOException;
/**********************************
* 用途说明: 文件自动备份
* 参数说明 taskId 节点ID
* 参数说明 nodeId 任务ID
* 返回值说明: com.yfd.platform.config.ResponseResult 返回成功或者失败
***********************************/
String automaticFileBackup(String taskId, String nodeId);
/**********************************
* 用途说明: 查询本地结构树
* 参数说明 taskId 节点ID
* 参数说明 nodeId 任务ID
* 参数说明 id 文件夹ID
* 返回值说明: com.yfd.platform.config.ResponseResult 返回双树数据
***********************************/
DualTreeResponse listLocalTree(String taskId, String nodeId, String id);
/**********************************
* 用途说明: 查询备份空间结构树
* 参数说明 taskId 节点ID
* 参数说明 nodeId 任务ID
* 参数说明 id 文件夹ID
* 返回值说明: com.yfd.platform.config.ResponseResult 返回双树数据
***********************************/
DualTreeResponse listBackupTree(String taskId, String nodeId, String id);
} }

View File

@ -3,8 +3,7 @@ package com.yfd.platform.modules.experimentalData.service.impl;
import cn.hutool.core.collection.CollUtil; import cn.hutool.core.collection.CollUtil;
import java.nio.channels.FileChannel;
import java.nio.channels.FileLock;
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.nio.file.attribute.BasicFileAttributes;
@ -15,6 +14,7 @@ import java.security.NoSuchAlgorithmException;
import java.text.SimpleDateFormat; import java.text.SimpleDateFormat;
import java.util.*; import java.util.*;
import java.util.concurrent.*; import java.util.concurrent.*;
import java.util.function.Function;
import java.util.regex.Matcher; import java.util.regex.Matcher;
import java.util.regex.Pattern; import java.util.regex.Pattern;
import java.util.stream.Collectors; import java.util.stream.Collectors;
@ -33,7 +33,6 @@ import com.opencsv.exceptions.CsvValidationException;
import com.yfd.platform.component.ServerSendEventServer; import com.yfd.platform.component.ServerSendEventServer;
import com.yfd.platform.config.ResponseResult; import com.yfd.platform.config.ResponseResult;
import com.yfd.platform.modules.experimentalData.domain.*; import com.yfd.platform.modules.experimentalData.domain.*;
import com.yfd.platform.modules.experimentalData.enums.CompressionFormat;
import com.yfd.platform.modules.experimentalData.mapper.TsFilesMapper; import com.yfd.platform.modules.experimentalData.mapper.TsFilesMapper;
import com.yfd.platform.modules.experimentalData.service.ITsFilesService; import com.yfd.platform.modules.experimentalData.service.ITsFilesService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
@ -51,7 +50,6 @@ import com.yfd.platform.system.domain.SysDictionaryItems;
import com.yfd.platform.system.mapper.SysDictionaryItemsMapper; import com.yfd.platform.system.mapper.SysDictionaryItemsMapper;
import com.yfd.platform.utils.StringUtils; import com.yfd.platform.utils.StringUtils;
import io.netty.channel.ChannelInboundHandlerAdapter; 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.SevenZArchiveEntry;
import org.apache.commons.compress.archivers.sevenz.SevenZFile; import org.apache.commons.compress.archivers.sevenz.SevenZFile;
import org.apache.commons.compress.archivers.sevenz.SevenZOutputFile; import org.apache.commons.compress.archivers.sevenz.SevenZOutputFile;
@ -68,9 +66,8 @@ import org.springframework.security.authentication.UsernamePasswordAuthenticatio
import org.springframework.security.core.context.SecurityContextHolder; import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional; import org.springframework.transaction.annotation.Transactional;
import org.springframework.beans.factory.annotation.Value; // 正确
import javax.annotation.Resource; import javax.annotation.Resource;
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;
@ -91,6 +88,7 @@ import org.apache.commons.codec.binary.Hex;
public class TsFilesServiceImpl extends ServiceImpl<TsFilesMapper, TsFiles> implements ITsFilesService { public class TsFilesServiceImpl extends ServiceImpl<TsFilesMapper, TsFiles> implements ITsFilesService {
private static final Logger LOGGER = LoggerFactory.getLogger(ChannelInboundHandlerAdapter.class); private static final Logger LOGGER = LoggerFactory.getLogger(ChannelInboundHandlerAdapter.class);
private int time = 1; private int time = 1;
//试验任务文档表 Mapper //试验任务文档表 Mapper
@ -115,7 +113,6 @@ public class TsFilesServiceImpl extends ServiceImpl<TsFilesMapper, TsFiles> impl
private final Set<String> addedEntries = new HashSet<>(); private final Set<String> addedEntries = new HashSet<>();
/********************************** /**********************************
* 用途说明: 分页查询试验数据管理-文档内容 * 用途说明: 分页查询试验数据管理-文档内容
* 参数说明 * 参数说明
@ -2502,8 +2499,15 @@ public class TsFilesServiceImpl extends ServiceImpl<TsFilesMapper, TsFiles> impl
TsFiles tsFiles = new TsFiles(); TsFiles tsFiles = new TsFiles();
try { try {
// 获取 MinIO 和本地文件列表并行处理 // 获取 MinIO 和本地文件列表并行处理
List<FileItemResult> fileItemListMinio = Collections.synchronizedList(new ArrayList<>()); // List<FileItemResult> fileItemListMinio = Collections.synchronizedList(new ArrayList<>());
List<FileItemResult> fileItemListLocal = Collections.synchronizedList(new ArrayList<>()); // List<FileItemResult> fileItemListLocal = Collections.synchronizedList(new ArrayList<>());
CopyOnWriteArrayList<FileItemResult> fileItemListMinio = new CopyOnWriteArrayList<>();
CopyOnWriteArrayList<FileItemResult> fileItemListLocal = new CopyOnWriteArrayList<>();
// 优化点3: 使用 CompletableFuture 进行并行任务管理
// final List<FileItemResult> minioFiles = Collections.synchronizedList(new ArrayList<>());
// final List<FileItemResult> localFiles = Collections.synchronizedList(new ArrayList<>());
if (StringUtils.isNoneEmpty(nodeId, taskId)) { if (StringUtils.isNoneEmpty(nodeId, taskId)) {
// 并行查询数据库记录 // 并行查询数据库记录
@ -2558,6 +2562,7 @@ public class TsFilesServiceImpl extends ServiceImpl<TsFilesMapper, TsFiles> impl
private QueryWrapper<TsFiles> buildTaskQuery(String nodeId, String taskId) { private QueryWrapper<TsFiles> buildTaskQuery(String nodeId, String taskId) {
return new QueryWrapper<TsFiles>() return new QueryWrapper<TsFiles>()
.eq("task_id", taskId) .eq("task_id", taskId)
.eq("parent_id", "00")
.eq("node_id", nodeId); .eq("node_id", nodeId);
//.and(wrapper -> wrapper.eq("work_path", "/").or().eq("backup_path", "/")); //.and(wrapper -> wrapper.eq("work_path", "/").or().eq("backup_path", "/"));
} }
@ -2569,51 +2574,31 @@ public class TsFilesServiceImpl extends ServiceImpl<TsFilesMapper, TsFiles> impl
} }
// 辅助方法获取文件列表并添加到集合 // 辅助方法获取文件列表并添加到集合
// 辅助方法获取文件列表并添加到集合优化版
// 优化点7提取文件处理核心逻辑
private void processFileList(String path, String fileName, String storageKey, List<FileItemResult> targetList, String isFile, String nodeId, String taskId) throws Exception { private void processFileList(String path, String fileName, String storageKey, List<FileItemResult> targetList, String isFile, String nodeId, String taskId) throws Exception {
if (StringUtils.isNotEmpty(path)) { if (StringUtils.isNotEmpty(path)) {
AbstractBaseFileService<?> service = storageSourceContext.getByStorageKey(storageKey); AbstractBaseFileService<?> service = storageSourceContext.getByStorageKey(storageKey);
String folderPath = path + fileName + "/";
Map<String, TsFiles> backupPathMap = preloadTsFiles(nodeId, taskId, "backup_path");
Map<String, TsFiles> workPathMap = preloadTsFiles(nodeId, taskId, "work_path");
if (storageKey.equals("minio")) { if (storageKey.equals("minio")) {
List<FileItemResult> files = service.fileListData(path, fileName + "/");
List<FileItemResult> files = new ArrayList<>();
if ("FILE".equals(isFile)) {
files = service.fileListData(path, fileName + "/");
} else {
files = service.fileLists(folderPath);
}
if (files != null) { if (files != null) {
// 对每个文件的路径进行规范化 // 对每个文件的路径进行规范化
// for (FileItemResult file : files) {
// String normalizedPath = ensurePathFormat(file.getPath());
// String ProcessingPath = processingPath(normalizedPath, nodeId);
// file.setPath(ProcessingPath);
// if (file.getSize() == null) {
// file.setSize((long) 0);
// } else {
// // 获取文件大小字节
// long fileSizeInBytes = file.getSize();
// // 转换为 MB 并保留两位小数
// double fileSizeInMB = fileSizeInBytes / (1024.0 * 1024.0);
// String fileSizeFormatted = String.format("%.2f", fileSizeInMB); // 保留两位小数
// // 判断是否为 "0.00"如果是则直接设置为 0
// if ("0.00".equals(fileSizeFormatted)) {
// file.setSize((long) 0); // 如果文件大小为 0.00直接设置为 0
// } else {
// // 否则将文件大小转换为 long去掉小数部分
// file.setSize((long) Double.parseDouble(fileSizeFormatted));
// }
// }
//
// QueryWrapper<TsFiles> queryWrapper = new QueryWrapper<>();
// queryWrapper.eq("node_id", nodeId);
// queryWrapper.eq("task_id", taskId);
// queryWrapper.eq("backup_path", normalizedPath);
// queryWrapper.eq("file_name", file.getName());
// TsFiles tsFiles1 = tsFilesMapper.selectOne(queryWrapper);
// if (tsFiles1 != null) {
// file.setParentId(tsFiles1.getParentId());
// file.setId(tsFiles1.getId());
// }
// }
files.forEach(file -> { files.forEach(file -> {
String normalizedPath = ensurePathFormat(file.getPath()); String normalizedPath = ensurePathFormat(file.getPath());
String ProcessingPath = processingPath(normalizedPath, nodeId); // String ProcessingPath = processingPath(normalizedPath, nodeId);
file.setPath(ProcessingPath); file.setPath(normalizedPath);
if (file.getSize() == null) { if (file.getSize() == null) {
file.setSize((long) 0); file.setSize((long) 0);
} else { } else {
@ -2631,15 +2616,18 @@ public class TsFilesServiceImpl extends ServiceImpl<TsFilesMapper, TsFiles> impl
} }
} }
QueryWrapper<TsFiles> queryWrapper = new QueryWrapper<>(); // QueryWrapper<TsFiles> queryWrapper = new QueryWrapper<>();
queryWrapper.eq("node_id", nodeId); // queryWrapper.eq("node_id", nodeId);
queryWrapper.eq("task_id", taskId); // queryWrapper.eq("task_id", taskId);
queryWrapper.eq("backup_path", normalizedPath); // queryWrapper.eq("backup_path", normalizedPath);
queryWrapper.eq("file_name", file.getName()); // queryWrapper.eq("file_name", file.getName());
TsFiles tsFiles1 = tsFilesMapper.selectOne(queryWrapper); // TsFiles tsFiles1 = tsFilesMapper.selectOne(queryWrapper);
if (tsFiles1 != null) {
file.setParentId(tsFiles1.getParentId()); TsFiles tsFileFromBackup = backupPathMap.get(normalizedPath + "|" + file.getName()); // backupPathMap 中获取 TsFiles 对象
file.setId(tsFiles1.getId());
if (tsFileFromBackup != null) {
file.setParentId(tsFileFromBackup.getParentId());
file.setId(tsFileFromBackup.getId());
} }
}); });
// 同步添加线程安全 // 同步添加线程安全
@ -2648,14 +2636,34 @@ public class TsFilesServiceImpl extends ServiceImpl<TsFilesMapper, TsFiles> impl
} }
} else { } else {
List<FileItemResult> files = service.fileListData(path, fileName);
List<FileItemResult> files = new ArrayList<>();
if ("FILE".equals(isFile)) {
files = service.fileListData(path, fileName + "/");
} else {
files = service.fileLists(folderPath);
}
if (files != null) { if (files != null) {
// 对每个文件的路径进行规范化 // 对每个文件的路径进行规范化
files.forEach(file -> { files.forEach(file -> {
String normalizedPath = ensurePathFormat(file.getPath()); String normalizedPath = ensurePathFormat(file.getPath());
// QueryWrapper<TsFiles> queryWrapper = new QueryWrapper<>();
// queryWrapper.eq("node_id", nodeId);
// queryWrapper.eq("task_id", taskId);
// queryWrapper.eq("work_path", normalizedPath);
// queryWrapper.eq("file_name", file.getName());
// TsFiles tsFiles1 = tsFilesMapper.selectOne(queryWrapper);
TsFiles tsFileFromWork = workPathMap.get(normalizedPath + "|" + file.getName()); // backupPathMap 中获取 TsFiles 对象
String ProcessingPath = processingPath(normalizedPath, nodeId); if (tsFileFromWork != null) {
file.setPath(ProcessingPath); file.setParentId(tsFileFromWork.getParentId());
file.setId(tsFileFromWork.getId());
}
// String ProcessingPath = processingPath(normalizedPath, nodeId);
file.setPath(normalizedPath);
if (file.getSize() == null) { if (file.getSize() == null) {
file.setSize((long) 0); file.setSize((long) 0);
} else { } else {
@ -2672,20 +2680,7 @@ public class TsFilesServiceImpl extends ServiceImpl<TsFilesMapper, TsFiles> impl
file.setSize((long) Double.parseDouble(fileSizeFormatted)); file.setSize((long) Double.parseDouble(fileSizeFormatted));
} }
} }
// file.setPath(normalizedPath);
QueryWrapper<TsFiles> queryWrapper = new QueryWrapper<>();
queryWrapper.eq("node_id", nodeId);
queryWrapper.eq("task_id", taskId);
queryWrapper.eq("work_path", normalizedPath);
queryWrapper.eq("file_name", file.getName());
TsFiles tsFiles1 = tsFilesMapper.selectOne(queryWrapper);
if (tsFiles1 != null) {
file.setParentId(tsFiles1.getParentId());
file.setId(tsFiles1.getId());
}
}); });
// 同步添加线程安全
targetList.addAll(files); targetList.addAll(files);
} }
@ -2694,6 +2689,33 @@ public class TsFilesServiceImpl extends ServiceImpl<TsFilesMapper, TsFiles> impl
} }
// 批量查询TsFiles记录按路径类型分类
// 批量查询TsFiles记录按路径类型分类
private Map<String, TsFiles> preloadTsFiles(String nodeId, String taskId, String pathType) {
QueryWrapper<TsFiles> queryWrapper = new QueryWrapper<>();
queryWrapper.eq("node_id", nodeId)
.eq("task_id", taskId)
.isNotNull(pathType); // 确保路径字段不为空
return tsFilesMapper.selectList(queryWrapper)
.stream()
.filter(tsFile -> {
// 确保路径字段不为空不管是 backup_path 还是 work_path
String path = pathType.equals("backup_path") ? tsFile.getBackupPath() : tsFile.getWorkPath();
return path != null && !path.isEmpty(); // 如果路径为空跳过
})
.collect(Collectors.toMap(
tsFile -> {
String path = pathType.equals("backup_path")
? tsFile.getBackupPath()
: tsFile.getWorkPath();
return path + "|" + tsFile.getFileName();
},
Function.identity()
));
}
/** /**
* 确保路径格式为以 "/" 开头和结尾例如 "/data/test/" * 确保路径格式为以 "/" 开头和结尾例如 "/data/test/"
* 若路径为空或非法返回根路径 "/" * 若路径为空或非法返回根路径 "/"
@ -2717,12 +2739,6 @@ public class TsFilesServiceImpl extends ServiceImpl<TsFilesMapper, TsFiles> impl
// 辅助方法去重文件列表并行安全 // 辅助方法去重文件列表并行安全
private void deduplicateFileList(List<FileItemResult> fileList) { private void deduplicateFileList(List<FileItemResult> fileList) {
// ConcurrentMap<String, Boolean> seenKeys = new ConcurrentHashMap<>();
// fileList.removeIf(file -> {
// String key = normalizePath(file.getPath()) + file.getName();
// return seenKeys.putIfAbsent(key, Boolean.TRUE) != null;
// });
ConcurrentHashMap<String, Boolean> seenKeys = new ConcurrentHashMap<>(); ConcurrentHashMap<String, Boolean> seenKeys = new ConcurrentHashMap<>();
List<FileItemResult> uniqueFiles = fileList.parallelStream() List<FileItemResult> uniqueFiles = fileList.parallelStream()
.filter(file -> seenKeys.putIfAbsent(generateMapKey(file), true) == null) .filter(file -> seenKeys.putIfAbsent(generateMapKey(file), true) == null)
@ -2834,8 +2850,8 @@ public class TsFilesServiceImpl extends ServiceImpl<TsFilesMapper, TsFiles> impl
List<FileItemResult> md5Mismatches, String nodeId) { List<FileItemResult> md5Mismatches, String nodeId) {
minioFile.setPath("/" + nodeId + minioFile.getPath()); // minioFile.setPath( minioFile.getPath());
localFile.setPath("/" + nodeId + localFile.getPath()); // localFile.setPath(localFile.getPath());
File localFileObj = new File(basePath + minioFile.getPath(), localFile.getName()); File localFileObj = new File(basePath + minioFile.getPath(), localFile.getName());
if (localFileObj.isDirectory()) { if (localFileObj.isDirectory()) {
LOGGER.warn("跳过文件夹: {}", localFileObj.getAbsolutePath()); LOGGER.warn("跳过文件夹: {}", localFileObj.getAbsolutePath());
@ -3119,6 +3135,68 @@ public class TsFilesServiceImpl extends ServiceImpl<TsFilesMapper, TsFiles> impl
} }
} }
/**********************************
* public String path;
* public String size;
* public String name;
* public String type;
* 用途说明: 文件自动备份
* 参数说明 taskId 节点ID
* 参数说明 nodeId 任务ID
* 返回值说明: com.yfd.platform.config.ResponseResult 返回成功或者失败
***********************************/
@Override
public String automaticFileBackup(String taskId, String nodeId) {
//首先查询节点下面所有 备份路径为空的数据
QueryWrapper<TsFiles> queryWrapper = new QueryWrapper<>();
queryWrapper.eq("task_id", taskId);
queryWrapper.eq("node_id", nodeId);
queryWrapper.and(wrapper -> wrapper.isNull("backup_path").or().eq("backup_path", ""));
queryWrapper.isNotNull("work_path").ne("work_path", "");
List<TsFiles> tsFilelist = tsFilesMapper.selectList(queryWrapper);
int FileCount = 0, FolderCount = 0;
int BackupsFileCount = 0, BackupsFolderCount = 0;
if (tsFilelist.isEmpty()) {
return "本地有新增文件 " + FileCount + " 个, 文件夹 " + FolderCount + " 个, 已将 " + BackupsFileCount + " 个文件, " + BackupsFolderCount + " 个文件夹备份成功";
}
for (TsFiles tsFiles : tsFilelist) {
ParameterList parameterList = new ParameterList();
Parameter fileParameter = new Parameter();
Parameter FolderParameter = new Parameter();
List<ParameterList> fileParameterlist = new ArrayList<>();
List<ParameterList> FolderParameterlist = new ArrayList<>();
if ("FILE".equals(tsFiles.getIsFile())) {
parameterList.setName(tsFiles.getFileName());
parameterList.setPath(tsFiles.getWorkPath());
parameterList.setSize(tsFiles.getFileSize());
parameterList.setType(tsFiles.getIsFile());
fileParameterlist.add(parameterList);
fileParameter.setParameterLists(fileParameterlist);
Boolean value = uploadToBackup(fileParameter);
if (value) {
BackupsFileCount++;
}
FileCount++;
} else {
parameterList.setName(tsFiles.getFileName());
parameterList.setPath(tsFiles.getWorkPath());
parameterList.setSize(tsFiles.getFileSize());
parameterList.setType(tsFiles.getIsFile());
FolderParameterlist.add(parameterList);
FolderParameter.setParameterLists(FolderParameterlist);
Boolean value = uploadToBackup(FolderParameter);
if (value) {
BackupsFolderCount++;
}
FolderCount++;
}
}
return "本地有新增文件 " + FileCount + " 个, 新增文件夹 " + FolderCount + " 个, 已将 " + BackupsFileCount + " 个文件, " + BackupsFolderCount + " 个文件夹备份成功";
}
/********************************** /**********************************
* 用途说明: 从备份空间下载到工作空间 * 用途说明: 从备份空间下载到工作空间
@ -3945,58 +4023,267 @@ public class TsFilesServiceImpl extends ServiceImpl<TsFilesMapper, TsFiles> impl
/**********************************************************复制文件或者文件夹结束***********************************************************************************/ /**********************************************************复制文件或者文件夹结束***********************************************************************************/
/********************************** /**********************************
* 用途说明: 查询本地和备份空间结构树 * 用途说明: 查询本地结构树
* 参数说明 taskId 节点ID * 参数说明 taskId 节点ID
* 参数说明 nodeId 任务ID * 参数说明 nodeId 任务ID
* 参数说明 id 文件夹ID
* 返回值说明: com.yfd.platform.config.ResponseResult 返回双树数据 * 返回值说明: com.yfd.platform.config.ResponseResult 返回双树数据
***********************************/ ***********************************/
@Override @Override
public DualTreeResponse listLocalAndBackup(String taskId, String nodeId) { public DualTreeResponse listLocalTree(String taskId, String nodeId, String id) {
// 记录方法入参 // 记录方法入参
LOGGER.info("Starting to build dual trees for taskId={}, nodeId={}", taskId, nodeId); LOGGER.info("Starting to build dual trees for taskId={}, nodeId={}", taskId, nodeId);
// 1. 批量查询所有相关节点 // 1. 批量查询所有相关节点
QueryWrapper<TsFiles> queryWrapper = new QueryWrapper<>(); QueryWrapper<TsFiles> queryWrapper = new QueryWrapper<>();
queryWrapper.eq("task_id", taskId) if (taskId != null && !taskId.isEmpty()) {
.eq("node_id", nodeId); queryWrapper.eq("task_id", taskId);
}
if (nodeId != null && !nodeId.isEmpty()) {
queryWrapper.eq("node_id", nodeId);
}
queryWrapper.isNotNull("work_path").ne("work_path", "");
;
if (id != null && !id.isEmpty()) {
// 查询 ID 等于给定 ID 的文件 或者 父节点等于给定 ID 的文件
queryWrapper.eq("parent_id", id);
// queryWrapper.eq("id", id).or().eq("parent_id", id);
} else {
queryWrapper.eq("parent_id", "00");
}
List<TsFiles> allNodes = tsFilesMapper.selectList(queryWrapper); List<TsFiles> allNodes = tsFilesMapper.selectList(queryWrapper);
// 2. 构建内存索引提升查询效率 // 2. 双树构建容器
List<TreeDTO> localTrees = new ArrayList<>();
if (allNodes.isEmpty()) {
return new DualTreeResponse(localTrees, null);
}
// 3. 构建内存索引提升查询效率
Map<String, List<TsFiles>> parentChildrenMap = allNodes.stream() Map<String, List<TsFiles>> parentChildrenMap = allNodes.stream()
.collect(Collectors.groupingBy(TsFiles::getParentId)); .collect(Collectors.groupingBy(TsFiles::getParentId));
LOGGER.debug("使用{}个条目构建父子映射", parentChildrenMap.size()); LOGGER.debug("使用{}个条目构建父子映射", parentChildrenMap.size());
// 3. 双树构建容器 if (id == null || id == "") {
List<TreeDTO> localTrees = new ArrayList<>(); List<TsFiles> rootNodes = parentChildrenMap.get("00");
List<TreeDTO> minioTrees = new ArrayList<>(); if (rootNodes == null || rootNodes.isEmpty()) {
LOGGER.warn("找不到的根节点 taskId={}, nodeId={}", taskId, nodeId);
return new DualTreeResponse(localTrees, null);
} else {
// 4. 从顶级节点parentId为00开始构建树 if (rootNodes != null) {
List<TsFiles> rootNodes = parentChildrenMap.get("00"); for (TsFiles rootNode : rootNodes) {
if (rootNodes == null || rootNodes.isEmpty()) { // 构建本地树
LOGGER.warn("找不到的根节点 taskId={}, nodeId={}", taskId, nodeId); TreeDTO localTree = buildFatherTree(rootNode, parentChildrenMap, true);
return new DualTreeResponse(localTrees, minioTrees); if (localTree != null) {
} localTrees.add(localTree);
LOGGER.debug("添加了本地树节点: {}", localTree.getId());
if (rootNodes != null) { }
for (TsFiles rootNode : rootNodes) { }
// 构建本地树
TreeDTO localTree = buildTree(rootNode, parentChildrenMap, true);
if (localTree != null) {
localTrees.add(localTree);
LOGGER.debug("添加了本地树节点: {}", localTree.getId());
} }
LOGGER.info("Tree construction completed. Local nodes: {}", localTrees.size());
}
// 构建Minio树 } else {
TreeDTO minioTree = buildTree(rootNode, parentChildrenMap, false); // 4. 从顶级节点parentId为00开始构建树
if (minioTree != null) { List<TsFiles> rootNodes = parentChildrenMap.get(id);
minioTrees.add(minioTree); if (rootNodes == null || rootNodes.isEmpty()) {
LOGGER.debug("添加了MINIO树节点: {}", minioTree.getId()); LOGGER.warn("找不到的根节点 taskId={}, nodeId={}", taskId, nodeId);
return new DualTreeResponse(localTrees, null);
}
if (rootNodes != null) {
for (TsFiles rootNode : rootNodes) {
// 构建本地树
TreeDTO localTree = buildFatherTree(rootNode, parentChildrenMap, true);
if (localTree != null) {
localTrees.add(localTree);
LOGGER.debug("添加了本地树节点: {}", localTree.getId());
}
} }
} }
LOGGER.info("Tree construction completed. Local nodes: {}", localTrees.size());
} }
LOGGER.info("Tree construction completed. Local nodes: {}, MinIO nodes: {}", localTrees.size(), minioTrees.size()); return new DualTreeResponse(localTrees, null);
return new DualTreeResponse(localTrees, minioTrees);
} }
/**********************************
* 用途说明: 查询备份空间结构树
* 参数说明 taskId 节点ID
* 参数说明 nodeId 任务ID
* 参数说明 id 文件夹ID
* 返回值说明: com.yfd.platform.config.ResponseResult 返回双树数据
***********************************/
@Override
public DualTreeResponse listBackupTree(String taskId, String nodeId, String id) {
// 记录方法入参
LOGGER.info("Starting to build dual trees for taskId={}, nodeId={}", taskId, nodeId);
// 1. 批量查询所有相关节点
QueryWrapper<TsFiles> queryWrapper = new QueryWrapper<>();
if (taskId != null && !taskId.isEmpty()) {
queryWrapper.eq("task_id", taskId);
}
if (nodeId != null && !nodeId.isEmpty()) {
queryWrapper.eq("node_id", nodeId);
}
queryWrapper.isNotNull("backup_path").ne("backup_path", "");
if (id != null && !id.isEmpty()) {
// 查询 ID 等于给定 ID 的文件 或者 父节点等于给定 ID 的文件
queryWrapper.eq("parent_id", id);
// queryWrapper.eq("id", id).or().eq("parent_id", id);
} else {
queryWrapper.eq("parent_id", "00");
}
List<TsFiles> allNodes = tsFilesMapper.selectList(queryWrapper);
// 2. 双树构建容器
List<TreeDTO> minioTrees = new ArrayList<>();
// 3. 构建内存索引提升查询效率
Map<String, List<TsFiles>> parentChildrenMap = allNodes.stream()
.collect(Collectors.groupingBy(TsFiles::getParentId));
LOGGER.debug("使用{}个条目构建父子映射", parentChildrenMap.size());
if (allNodes.isEmpty()) {
return new DualTreeResponse(null, minioTrees);
}
if (id == null || id == "") {
List<TsFiles> rootNodes = parentChildrenMap.get("00");
if (rootNodes == null || rootNodes.isEmpty()) {
LOGGER.warn("找不到的根节点 taskId={}, nodeId={}", taskId, nodeId);
return new DualTreeResponse(null, minioTrees);
} else {
if (rootNodes != null) {
for (TsFiles rootNode : rootNodes) {
// 构建Minio树
TreeDTO minioTree = buildFatherTree(rootNode, parentChildrenMap, false);
if (minioTree != null) {
minioTrees.add(minioTree);
LOGGER.debug("添加了MINIO树节点: {}", minioTree.getId());
}
}
}
LOGGER.info("Tree construction completed. MinIO nodes: {}", minioTrees.size());
}
} else {
// 4. 从顶级节点parentId为00开始构建树
List<TsFiles> rootNodes = parentChildrenMap.get(id);
if (rootNodes == null || rootNodes.isEmpty()) {
LOGGER.warn("找不到的根节点 taskId={}, nodeId={}", taskId, nodeId);
return new DualTreeResponse(null, minioTrees);
}
if (rootNodes != null) {
for (TsFiles rootNode : rootNodes) {
// 构建Minio树
TreeDTO minioTree = buildFatherTree(rootNode, parentChildrenMap, false);
if (minioTree != null) {
minioTrees.add(minioTree);
LOGGER.debug("添加了MINIO树节点: {}", minioTree.getId());
}
}
}
LOGGER.info("Tree construction completed. MinIO nodes: {}", minioTrees.size());
}
return new DualTreeResponse(null, minioTrees);
}
// /**********************************
// * 用途说明: 查询本地和备份空间结构树
// * 参数说明 taskId 节点ID
// * 参数说明 nodeId 任务ID
// * 返回值说明: com.yfd.platform.config.ResponseResult 返回双树数据
// ***********************************/
// @Override
// public DualTreeResponse listLocalAndBackup(String taskId, String nodeId, String id) {
// // 记录方法入参
// LOGGER.info("Starting to build dual trees for taskId={}, nodeId={}", taskId, nodeId);
// // 1. 批量查询所有相关节点
// QueryWrapper<TsFiles> queryWrapper = new QueryWrapper<>();
// if (taskId != null && !taskId.isEmpty()) {
// queryWrapper.eq("task_id", taskId);
// }
// if (nodeId != null && !nodeId.isEmpty()) {
// queryWrapper.eq("node_id", nodeId);
// }
//
// if (id != null && !id.isEmpty()) {
// // 查询 ID 等于给定 ID 的文件 或者 父节点等于给定 ID 的文件
// queryWrapper.eq("parent_id", id);
//// queryWrapper.eq("id", id).or().eq("parent_id", id);
// } else {
// queryWrapper.eq("parent_id", "00");
// }
// 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<>();
//
// if (id == null || id == "") {
// List<TsFiles> rootNodes = parentChildrenMap.get("00");
// if (rootNodes == null || rootNodes.isEmpty()) {
// LOGGER.warn("找不到的根节点 taskId={}, nodeId={}", taskId, nodeId);
// return new DualTreeResponse(localTrees, minioTrees);
// } else {
//
// if (rootNodes != null) {
// for (TsFiles rootNode : rootNodes) {
// // 构建本地树
// TreeDTO localTree = buildFatherTree(rootNode, parentChildrenMap, true);
// if (localTree != null) {
// localTrees.add(localTree);
// LOGGER.debug("添加了本地树节点: {}", localTree.getId());
// }
//
// // 构建Minio树
// TreeDTO minioTree = buildFatherTree(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());
// }
//
// } else {
// // 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);
// }
/** /**
* 递归构建树形结构内存操作不再查询数据库 * 递归构建树形结构内存操作不再查询数据库
* *
@ -4027,6 +4314,25 @@ public class TsFilesServiceImpl extends ServiceImpl<TsFilesMapper, TsFiles> impl
return dto; return dto;
} }
/**
* 递归构建父节点树形结构内存操作不再查询数据库
*
* @param current 当前节点
* @param parentChildrenMap 父子关系映射表
* @param isLocal 是否是本地树
* @return 有效的树节点路径不为空
*/
private TreeDTO buildFatherTree(TsFiles current, Map<String, List<TsFiles>> parentChildrenMap, boolean isLocal) {
// 1. 转换为DTO并检查路径有效性
TreeDTO dto = convertToDTO(current, isLocal);
if (dto.getPath() == null || dto.getPath().trim().isEmpty()) {
LOGGER.warn("由于路径为空,跳过节点{}", current.getId());
return null;
}
return dto;
}
/** /**
* FileNode 转换为 TreeDTO * FileNode 转换为 TreeDTO
* *
@ -4040,7 +4346,18 @@ public class TsFilesServiceImpl extends ServiceImpl<TsFilesMapper, TsFiles> impl
queryWrapperSysDictionary.eq("parentcode", "compressType"); queryWrapperSysDictionary.eq("parentcode", "compressType");
queryWrapperSysDictionary.orderByAsc("orderno"); queryWrapperSysDictionary.orderByAsc("orderno");
List<SysDictionaryItems> sysDictionaryItems = sysDictionaryItemsMapper.selectList(queryWrapperSysDictionary); List<SysDictionaryItems> sysDictionaryItems = sysDictionaryItemsMapper.selectList(queryWrapperSysDictionary);
int count = 0;
if ("FOLDER".equals(node.getIsFile())) {
QueryWrapper<TsFiles> queryWrapper = new QueryWrapper<>();
queryWrapper.eq("parent_id", node.getId());
if (isLocal) {
queryWrapper.isNotNull("work_path").ne("work_path", "");
} else {
queryWrapper.isNotNull("backup_path").ne("backup_path", "");
}
count = tsFilesMapper.selectCount(queryWrapper);
}
TreeDTO dto = new TreeDTO(); TreeDTO dto = new TreeDTO();
// 复制公共字段 // 复制公共字段
@ -4056,7 +4373,7 @@ public class TsFilesServiceImpl extends ServiceImpl<TsFilesMapper, TsFiles> impl
dto.setUploadTime(node.getUploadTime()); dto.setUploadTime(node.getUploadTime());
dto.setUploader(node.getUploader()); dto.setUploader(node.getUploader());
dto.setUpdateTime(node.getUpdateTime()); dto.setUpdateTime(node.getUpdateTime());
dto.setNumber(count);
//查询本地 //查询本地
if (isLocal) { if (isLocal) {
String workPath = node.getWorkPath(); String workPath = node.getWorkPath();
@ -4069,6 +4386,9 @@ public class TsFilesServiceImpl extends ServiceImpl<TsFilesMapper, TsFiles> impl
String path = workPath + fileNameData; String path = workPath + fileNameData;
//准备获取文件的信息 //准备获取文件的信息
if ("FILE".equals(node.getIsFile())) { if ("FILE".equals(node.getIsFile())) {
// dto.setUrl(null);
// dto.setType(null);
LOGGER.info("查询本地树的时候" + path); LOGGER.info("查询本地树的时候" + path);
AbstractBaseFileService<?> fileService = storageSourceContext.getByStorageKey("local"); AbstractBaseFileService<?> fileService = storageSourceContext.getByStorageKey("local");
FileItemResult fileItemResult = fileService.getFileItem(path); FileItemResult fileItemResult = fileService.getFileItem(path);

View File

@ -59,10 +59,10 @@ public abstract class AbstractS3BaseFileService<P extends S3BaseParam> extends A
return s3FileList(folderPath); return s3FileList(folderPath);
} }
// @Override @Override
// public List<FileItemResult> fileLists(String folderPath) { public List<FileItemResult> fileLists(String folderPath) {
// return s3FileLists(folderPath); return s3FileLists(folderPath);
// } }
@Override @Override
public List<FileItemResult> fileListData(String path, String name ) { public List<FileItemResult> fileListData(String path, String name ) {
return s3FileListData(path,name); return s3FileListData(path,name);
@ -353,86 +353,87 @@ public abstract class AbstractS3BaseFileService<P extends S3BaseParam> extends A
return path.startsWith("/") ? path : "/" + path; return path.startsWith("/") ? path : "/" + path;
} }
//这个方法有用 获取指定路径下的所有的文件以及文件夹 //这个方法有用 获取指定路径下的所有的文件以及文件夹
// public List<FileItemResult> s3FileLists(String path) { public List<FileItemResult> s3FileLists(String path) {
// String bucketName = param.getBucketName(); String bucketName = param.getBucketName();
// path = StringUtils.trimStartSlashes(path); // 去掉路径开头的斜杠 path = StringUtils.trimStartSlashes(path); // 去掉路径开头的斜杠
// String fullPath = StringUtils.trimStartSlashes(StringUtils.concat(param.getBasePath(), path, ZFileConstant.PATH_SEPARATOR)); String fullPath = StringUtils.trimStartSlashes(StringUtils.concat(param.getBasePath(), path, ZFileConstant.PATH_SEPARATOR));
//
// List<FileItemResult> fileItemList = new ArrayList<>(); List<FileItemResult> fileItemList = new ArrayList<>();
//
// // 调用递归方法获取文件列表 // 调用递归方法获取文件列表
// listFilesInDirectory(bucketName, fullPath, path, fileItemList); listFilesInDirectory(bucketName, fullPath, path, fileItemList);
//
// return fileItemList; return fileItemList;
// } }
//
// private void listFilesInDirectory(String bucketName, String fullPath, String path, List<FileItemResult> fileItemList) { private void listFilesInDirectory(String bucketName, String fullPath, String path, List<FileItemResult> fileItemList) {
// ListObjectsRequest listObjectsRequest = new ListObjectsRequest() ListObjectsRequest listObjectsRequest = new ListObjectsRequest()
// .withBucketName(bucketName) .withBucketName(bucketName)
// .withPrefix(fullPath) // 设置前缀为当前路径 .withPrefix(fullPath) // 设置前缀为当前路径
// .withMaxKeys(1000) // 每次最多返回 1000 个对象 .withMaxKeys(1000) // 每次最多返回 1000 个对象
// .withDelimiter("/"); // 使用 "/" 作为分隔符 .withDelimiter("/"); // 使用 "/" 作为分隔符
//
// ObjectListing objectListing = s3Client.listObjects(listObjectsRequest); ObjectListing objectListing = s3Client.listObjects(listObjectsRequest);
// boolean isFirstWhile = true; boolean isFirstWhile = true;
//
// do { do {
// if (!isFirstWhile) { if (!isFirstWhile) {
// objectListing = s3Client.listNextBatchOfObjects(objectListing); // 处理分页 objectListing = s3Client.listNextBatchOfObjects(objectListing); // 处理分页
// } }
//
// // 处理文件 // 处理文件
// for (S3ObjectSummary s : objectListing.getObjectSummaries()) { for (S3ObjectSummary s : objectListing.getObjectSummaries()) {
// FileItemResult fileItemResult = new FileItemResult(); FileItemResult fileItemResult = new FileItemResult();
//
// // 跳过当前目录本身 // 跳过当前目录本身
// if (s.getKey().equals(fullPath)) { if (s.getKey().equals(fullPath)) {
// continue; continue;
// } }
//
// // 获取文件名并去除前导斜杠 // 获取文件名并去除前导斜杠
// String fileName = s.getKey().substring(fullPath.length()); String fileName = s.getKey().substring(fullPath.length());
// if (fileName.startsWith(ZFileConstant.PATH_SEPARATOR)) { if (fileName.startsWith(ZFileConstant.PATH_SEPARATOR)) {
// fileName = fileName.substring(1); // 去掉开头的斜杠 fileName = fileName.substring(1); // 去掉开头的斜杠
// } }
//
// fileItemResult.setName(fileName); fileItemResult.setName(fileName);
// fileItemResult.setSize(s.getSize()); fileItemResult.setSize(s.getSize());
// fileItemResult.setTime(s.getLastModified()); fileItemResult.setTime(s.getLastModified());
// fileItemResult.setType(FileTypeEnum.FILE); fileItemResult.setType(FileTypeEnum.FILE);
// fileItemResult.setPath(path); // 当前路径 fileItemResult.setPath(path); // 当前路径
//
// // 构造完整路径并生成下载 URL // 构造完整路径并生成下载 URL
// String fullPathAndName = StringUtils.concat(path, fileItemResult.getName()); String fullPathAndName = StringUtils.concat(path, fileItemResult.getName());
// fileItemResult.setUrl(getDownloadUrl(fullPathAndName)); fileItemResult.setUrl(getDownloadUrl(fullPathAndName));
//
// fileItemList.add(fileItemResult); fileItemList.add(fileItemResult);
// } }
//
// // 处理文件夹 // 处理文件夹
// for (String commonPrefix : objectListing.getCommonPrefixes()) { for (String commonPrefix : objectListing.getCommonPrefixes()) {
// FileItemResult fileItemResult = new FileItemResult(); FileItemResult fileItemResult = new FileItemResult();
//
// // 获取文件夹名称去掉前导路径并修正末尾斜杠 // 获取文件夹名称去掉前导路径并修正末尾斜杠
// String folderName = commonPrefix.substring(fullPath.length(), commonPrefix.length() - 1); String folderName = commonPrefix.substring(fullPath.length(), commonPrefix.length() - 1);
// if (StrUtil.isEmpty(folderName) || StrUtil.equals(folderName, StringUtils.DELIMITER_STR)) { if (StrUtil.isEmpty(folderName) || StrUtil.equals(folderName, StringUtils.DELIMITER_STR)) {
// continue; // 跳过无效的文件夹名称 continue; // 跳过无效的文件夹名称
// } }
//
// fileItemResult.setName(folderName); fileItemResult.setName(folderName);
// fileItemResult.setType(FileTypeEnum.FOLDER); fileItemResult.setType(FileTypeEnum.FOLDER);
// fileItemResult.setPath(path); // 当前路径 fileItemResult.setPath(path); // 当前路径
// fileItemList.add(fileItemResult);
// fileItemList.add(fileItemResult);
// // 递归处理子文件夹
// String subFolderPath = path + folderName + ZFileConstant.PATH_SEPARATOR; // 修正路径拼接 // 递归处理子文件夹
// String subFolderFullPath = commonPrefix; // 子文件夹的完整路径 String subFolderPath = path + folderName + ZFileConstant.PATH_SEPARATOR; // 修正路径拼接
// listFilesInDirectory(bucketName, subFolderFullPath, subFolderPath, fileItemList); String subFolderFullPath = commonPrefix; // 子文件夹的完整路径
// } listFilesInDirectory(bucketName, subFolderFullPath, subFolderPath, fileItemList);
// }
// isFirstWhile = false;
// } while (objectListing.isTruncated()); // 处理分页 isFirstWhile = false;
// } } while (objectListing.isTruncated()); // 处理分页
}
@Override @Override

View File

@ -262,17 +262,17 @@ public interface BaseFileService {
*/ */
S3Object getObject(String bucketName, String key); S3Object getObject(String bucketName, String key);
// /*** /***
// * 获取指定路径下的文件及文件夹 * 获取指定路径下的文件及文件夹
// * *
// * @param folderPath * @param folderPath
// * 文件夹路径 * 文件夹路径
// * *
// * @return 文件及文件夹列表 * @return 文件及文件夹列表
// * *
// * @throws Exception 获取文件列表中出现的异常 / * @throws Exception 获取文件列表中出现的异常 /
// */ */
// List<FileItemResult> fileLists(String folderPath) throws Exception; List<FileItemResult> fileLists(String folderPath) throws Exception;
/*** /***
* 获取指定路径下的文件及文件夹 * 获取指定路径下的文件及文件夹

View File

@ -359,79 +359,82 @@ public class LocalServiceImpl extends AbstractProxyTransferService<LocalParam> {
} }
//以下是通过路径获取所有的文件以及文件夹 //以下是通过路径获取所有的文件以及文件夹
// @Override @Override
// public List<FileItemResult> fileLists(String folderPath) throws Exception { public List<FileItemResult> fileLists(String folderPath) throws Exception {
// checkPathSecurity(folderPath); checkPathSecurity(folderPath);
//
// List<FileItemResult> fileItemList = new ArrayList<>();
//
// String fullPath = StringUtils.concat(param.getFilePath() + folderPath);
//
// File file = new File(fullPath);
//
// if (!file.exists()) {
// throw new FileNotFoundException("文件不存在");
// }
//
// // 调用递归方法处理文件夹及其内容跳过第一个文件夹
// listFilesInDirectory(file, folderPath, fileItemList, true);
//
// return fileItemList;
// }
// private void listFilesInDirectory(File file, String folderPath, List<FileItemResult> fileItemList, boolean skipFirstFolder) throws IOException { List<FileItemResult> fileItemList = new ArrayList<>();
// // 跳过第一个文件夹folderPath从它下面的内容开始处理
// if (skipFirstFolder) { String fullPath = StringUtils.concat(param.getFilePath() + folderPath);
// // 如果当前文件是 folderPath, 直接跳过开始处理它的子文件夹
// if (file.isDirectory()) { File file = new File(fullPath);
// File[] files = file.listFiles();
// if (files != null) { if (!file.exists()) {
// for (File f : files) { throw new FileNotFoundException("文件不存在");
// // 递归进入下一级文件夹路径应该是 folderPath + 当前文件夹名 }
// listFilesInDirectory(f, folderPath, fileItemList, false);
// } // 调用递归方法处理文件夹及其内容跳过第一个文件夹
// } listFilesInDirectory(file, folderPath, fileItemList, true);
// }
// } else { return fileItemList;
// // 处理当前的文件夹或文件 }
// if (file.isDirectory()) {
// // 对于文件夹路径是 folderPath private void listFilesInDirectory(File file, String folderPath, List<FileItemResult> fileItemList, boolean skipFirstFolder) throws IOException {
// fileItemList.add(fileToFileItems(file, folderPath)); // 跳过第一个文件夹folderPath从它下面的内容开始处理
// if (skipFirstFolder) {
// // 递归处理当前文件夹内部的文件和文件夹 // 如果当前文件是 folderPath, 直接跳过开始处理它的子文件夹
// File[] files = file.listFiles(); if (file.isDirectory()) {
// if (files != null) { File[] files = file.listFiles();
// for (File f : files) { if (files != null) {
// // 递归进入下一级文件夹路径是 folderPath + 当前文件夹名 for (File f : files) {
// String newPath = folderPath + file.getName(); // 递归进入下一级文件夹路径应该是 folderPath + 当前文件夹名
// listFilesInDirectory(f, newPath, fileItemList, false); listFilesInDirectory(f, folderPath, fileItemList, false);
// } }
// } }
// } else { }
// // 对于文件路径是 folderPath } else {
// fileItemList.add(fileToFileItems(file, folderPath)); // 处理当前的文件夹或文件
// } if (file.isDirectory()) {
// } // 对于文件夹路径是 folderPath
// } fileItemList.add(fileToFileItems(file, folderPath));
// //lilin增加
// private FileItemResult fileToFileItems(File file, String folderPath) { // 递归处理当前文件夹内部的文件和文件夹
// FileItemResult result = new FileItemResult(); File[] files = file.listFiles();
// result.setName(file.getName()); if (files != null) {
// result.setPath(folderPath); // 这里返回的是父目录路径不包含文件名 for (File f : files) {
// // 递归进入下一级文件夹路径是 folderPath + 当前文件夹名
// // 使用 FileTypeEnum 设置文件类型 String newPath = folderPath + file.getName();
// if (file.isDirectory()) { listFilesInDirectory(f, newPath, fileItemList, false);
// result.setType(FileTypeEnum.FOLDER); }
// } else { }
// result.setType(FileTypeEnum.FILE); } else {
// } // 对于文件路径是 folderPath
// fileItemList.add(fileToFileItems(file, folderPath));
// result.setSize(file.length()); }
// // 设置文件的修改时间为 Date 类型 }
// result.setTime(new Date(file.lastModified())); }
// //lilin增加
// return result; private FileItemResult fileToFileItems(File file, String folderPath) {
// } FileItemResult result = new FileItemResult();
result.setName(file.getName());
result.setPath(folderPath); // 这里返回的是父目录路径不包含文件名
// 使用 FileTypeEnum 设置文件类型
if (file.isDirectory()) {
result.setType(FileTypeEnum.FOLDER);
} else {
result.setType(FileTypeEnum.FILE);
if (file.isFile()) {
result.setUrl(getDownloadUrl(folderPath + file.getName()));
}
}
result.setSize(file.length());
// 设置文件的修改时间为 Date 类型
result.setTime(new Date(file.lastModified()));
return result;
}
@Override @Override