提交代码
This commit is contained in:
parent
a86bd18f4f
commit
2939613be8
@ -377,23 +377,58 @@ public class TsFilesController {
|
||||
|
||||
|
||||
/**********************************
|
||||
* 用途说明: 查询本地和备份空间结构树
|
||||
* 用途说明: 查询本地结构树
|
||||
* 参数说明 taskId 节点ID
|
||||
* 参数说明 nodeId 任务ID
|
||||
* 参数说明 id 文件夹ID
|
||||
* 返回值说明: com.yfd.platform.config.ResponseResult 返回双树数据
|
||||
***********************************/
|
||||
@Log(module = "实验数据管理", value = "查询本地和备份空间结构树!")
|
||||
@PostMapping("/listLocalAndBackup")
|
||||
@ApiOperation("查询本地和备份空间结构树")
|
||||
public ResponseResult listLocalAndBackup(String taskId, String nodeId) {
|
||||
@Log(module = "实验数据管理", value = "查询本地结构树!")
|
||||
@PostMapping("/listLocalTree")
|
||||
@ApiOperation("查询本地结构树")
|
||||
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("参数为空");
|
||||
}
|
||||
//查询本地树和minio树
|
||||
DualTreeResponse response = tsFilesService.listLocalAndBackup(taskId, nodeId);
|
||||
return ResponseResult.successData(response);
|
||||
return ResponseResult.success(tsFilesService.automaticFileBackup(taskId,nodeId));
|
||||
}
|
||||
|
||||
|
||||
@ -430,6 +465,7 @@ public class TsFilesController {
|
||||
/**********************************
|
||||
* 用途说明: 查询文件内容接口
|
||||
* 参数说明 id 文件的ID
|
||||
* 参数说明 type 查看本地还是minio local minio
|
||||
* 返回值说明: com.yfd.platform.config.ResponseResult文件内容的纯文本(UTF-8 编码)
|
||||
***********************************/
|
||||
@Log(module = "实验数据管理", value = "查询文件内容!")
|
||||
@ -437,7 +473,7 @@ public class TsFilesController {
|
||||
@ApiOperation("查询文件内容")
|
||||
public ResponseResult getFileContent(@RequestParam String id) {
|
||||
try {
|
||||
if (StrUtil.isBlank(id)) {
|
||||
if (StrUtil.isBlank(id) ) {
|
||||
return ResponseResult.error("参数为空");
|
||||
}
|
||||
String content = tsFilesService.readFileContent(id);
|
||||
|
@ -101,4 +101,7 @@ public class TreeDTO {
|
||||
// 子节点列表
|
||||
// 初始化 children 为一个空列表
|
||||
private List<TreeDTO> children = new ArrayList<>();
|
||||
|
||||
@TableField(exist = false)
|
||||
private int number;
|
||||
}
|
||||
|
@ -140,13 +140,14 @@ public interface ITsFilesService extends IService<TsFiles> {
|
||||
*/
|
||||
String copyFileFolder(MoveCopyFileFolderRequest request)throws IOException;
|
||||
|
||||
/**********************************
|
||||
* 用途说明: 查询本地和备份空间结构树
|
||||
* 参数说明 taskId 节点ID
|
||||
* 参数说明 nodeId 任务ID
|
||||
* 返回值说明: com.yfd.platform.config.ResponseResult 返回双树数据
|
||||
***********************************/
|
||||
DualTreeResponse listLocalAndBackup(String taskId, String nodeId);
|
||||
// /**********************************
|
||||
// * 用途说明: 查询本地和备份空间结构树
|
||||
// * 参数说明 taskId 节点ID
|
||||
// * 参数说明 nodeId 任务ID
|
||||
// * 参数说明 id 文件夹ID
|
||||
// * 返回值说明: com.yfd.platform.config.ResponseResult 返回双树数据
|
||||
// ***********************************/
|
||||
// DualTreeResponse listLocalAndBackup(String taskId, String nodeId,String id);
|
||||
|
||||
|
||||
/**
|
||||
@ -181,4 +182,29 @@ public interface ITsFilesService extends IService<TsFiles> {
|
||||
* 返回值说明: com.yfd.platform.config.ResponseResult操作结果
|
||||
***********************************/
|
||||
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);
|
||||
}
|
||||
|
@ -3,8 +3,7 @@ package com.yfd.platform.modules.experimentalData.service.impl;
|
||||
import cn.hutool.core.collection.CollUtil;
|
||||
|
||||
|
||||
import java.nio.channels.FileChannel;
|
||||
import java.nio.channels.FileLock;
|
||||
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.nio.file.*;
|
||||
import java.nio.file.attribute.BasicFileAttributes;
|
||||
@ -15,6 +14,7 @@ import java.security.NoSuchAlgorithmException;
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.*;
|
||||
import java.util.concurrent.*;
|
||||
import java.util.function.Function;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
import java.util.stream.Collectors;
|
||||
@ -33,7 +33,6 @@ import com.opencsv.exceptions.CsvValidationException;
|
||||
import com.yfd.platform.component.ServerSendEventServer;
|
||||
import com.yfd.platform.config.ResponseResult;
|
||||
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.service.ITsFilesService;
|
||||
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.utils.StringUtils;
|
||||
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;
|
||||
@ -68,9 +66,8 @@ import org.springframework.security.authentication.UsernamePasswordAuthenticatio
|
||||
import org.springframework.security.core.context.SecurityContextHolder;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
import org.springframework.beans.factory.annotation.Value; // 正确
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import javax.xml.crypto.Data;
|
||||
import java.io.*;
|
||||
import java.sql.Timestamp;
|
||||
import java.time.LocalDateTime;
|
||||
@ -91,6 +88,7 @@ import org.apache.commons.codec.binary.Hex;
|
||||
public class TsFilesServiceImpl extends ServiceImpl<TsFilesMapper, TsFiles> implements ITsFilesService {
|
||||
private static final Logger LOGGER = LoggerFactory.getLogger(ChannelInboundHandlerAdapter.class);
|
||||
|
||||
|
||||
private int time = 1;
|
||||
|
||||
//试验任务文档表 Mapper
|
||||
@ -115,7 +113,6 @@ public class TsFilesServiceImpl extends ServiceImpl<TsFilesMapper, TsFiles> impl
|
||||
private final Set<String> addedEntries = new HashSet<>();
|
||||
|
||||
|
||||
|
||||
/**********************************
|
||||
* 用途说明: 分页查询试验数据管理-文档内容
|
||||
* 参数说明
|
||||
@ -2502,8 +2499,15 @@ public class TsFilesServiceImpl extends ServiceImpl<TsFilesMapper, TsFiles> impl
|
||||
TsFiles tsFiles = new TsFiles();
|
||||
try {
|
||||
// 获取 MinIO 和本地文件列表(并行处理)
|
||||
List<FileItemResult> fileItemListMinio = Collections.synchronizedList(new ArrayList<>());
|
||||
List<FileItemResult> fileItemListLocal = Collections.synchronizedList(new ArrayList<>());
|
||||
// List<FileItemResult> fileItemListMinio = 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)) {
|
||||
// 并行查询数据库记录
|
||||
@ -2558,6 +2562,7 @@ public class TsFilesServiceImpl extends ServiceImpl<TsFilesMapper, TsFiles> impl
|
||||
private QueryWrapper<TsFiles> buildTaskQuery(String nodeId, String taskId) {
|
||||
return new QueryWrapper<TsFiles>()
|
||||
.eq("task_id", taskId)
|
||||
.eq("parent_id", "00")
|
||||
.eq("node_id", nodeId);
|
||||
//.and(wrapper -> wrapper.eq("work_path", "/").or().eq("backup_path", "/"));
|
||||
}
|
||||
@ -2569,77 +2574,60 @@ 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 {
|
||||
if (StringUtils.isNotEmpty(path)) {
|
||||
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")) {
|
||||
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) {
|
||||
// 对每个文件的路径进行规范化
|
||||
// for (FileItemResult file : files) {
|
||||
// String normalizedPath = ensurePathFormat(file.getPath());
|
||||
files.forEach(file -> {
|
||||
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));
|
||||
// }
|
||||
// }
|
||||
//
|
||||
file.setPath(normalizedPath);
|
||||
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.001); // 如果文件大小为 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());
|
||||
// }
|
||||
// }
|
||||
|
||||
TsFiles tsFileFromBackup = backupPathMap.get(normalizedPath + "|" + file.getName()); // 从 backupPathMap 中获取 TsFiles 对象
|
||||
|
||||
files.forEach(file -> {
|
||||
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.001); // 如果文件大小为 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());
|
||||
if (tsFileFromBackup != null) {
|
||||
file.setParentId(tsFileFromBackup.getParentId());
|
||||
file.setId(tsFileFromBackup.getId());
|
||||
}
|
||||
});
|
||||
// 同步添加(线程安全)
|
||||
@ -2648,14 +2636,34 @@ public class TsFilesServiceImpl extends ServiceImpl<TsFilesMapper, TsFiles> impl
|
||||
|
||||
}
|
||||
} 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) {
|
||||
// 对每个文件的路径进行规范化
|
||||
files.forEach(file -> {
|
||||
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);
|
||||
file.setPath(ProcessingPath);
|
||||
if (tsFileFromWork != null) {
|
||||
file.setParentId(tsFileFromWork.getParentId());
|
||||
file.setId(tsFileFromWork.getId());
|
||||
}
|
||||
|
||||
// String ProcessingPath = processingPath(normalizedPath, nodeId);
|
||||
file.setPath(normalizedPath);
|
||||
if (file.getSize() == null) {
|
||||
file.setSize((long) 0);
|
||||
} else {
|
||||
@ -2672,20 +2680,7 @@ public class TsFilesServiceImpl extends ServiceImpl<TsFilesMapper, TsFiles> impl
|
||||
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);
|
||||
|
||||
}
|
||||
@ -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/")
|
||||
* 若路径为空或非法,返回根路径 "/"
|
||||
@ -2717,12 +2739,6 @@ public class TsFilesServiceImpl extends ServiceImpl<TsFilesMapper, TsFiles> impl
|
||||
|
||||
// 辅助方法:去重文件列表(并行安全)
|
||||
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<>();
|
||||
List<FileItemResult> uniqueFiles = fileList.parallelStream()
|
||||
.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) {
|
||||
|
||||
|
||||
minioFile.setPath("/" + nodeId + minioFile.getPath());
|
||||
localFile.setPath("/" + nodeId + localFile.getPath());
|
||||
// minioFile.setPath( minioFile.getPath());
|
||||
// localFile.setPath(localFile.getPath());
|
||||
File localFileObj = new File(basePath + minioFile.getPath(), localFile.getName());
|
||||
if (localFileObj.isDirectory()) {
|
||||
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
|
||||
* 参数说明 nodeId 任务ID
|
||||
* 参数说明 id 文件夹ID
|
||||
* 返回值说明: com.yfd.platform.config.ResponseResult 返回双树数据
|
||||
***********************************/
|
||||
@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);
|
||||
// 1. 批量查询所有相关节点
|
||||
QueryWrapper<TsFiles> queryWrapper = new QueryWrapper<>();
|
||||
queryWrapper.eq("task_id", taskId)
|
||||
.eq("node_id", nodeId);
|
||||
if (taskId != null && !taskId.isEmpty()) {
|
||||
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);
|
||||
|
||||
// 2. 构建内存索引提升查询效率
|
||||
// 2. 双树构建容器
|
||||
List<TreeDTO> localTrees = new ArrayList<>();
|
||||
if (allNodes.isEmpty()) {
|
||||
return new DualTreeResponse(localTrees, null);
|
||||
}
|
||||
// 3. 构建内存索引提升查询效率
|
||||
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)开始构建树
|
||||
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);
|
||||
return new DualTreeResponse(localTrees, null);
|
||||
} else {
|
||||
|
||||
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());
|
||||
}
|
||||
|
||||
} else {
|
||||
// 4. 从顶级节点(parentId为00)开始构建树
|
||||
List<TsFiles> rootNodes = parentChildrenMap.get(id);
|
||||
if (rootNodes == null || rootNodes.isEmpty()) {
|
||||
LOGGER.warn("找不到的根节点 taskId={}, nodeId={}", taskId, nodeId);
|
||||
return new DualTreeResponse(localTrees, null);
|
||||
}
|
||||
|
||||
if (rootNodes != null) {
|
||||
for (TsFiles rootNode : rootNodes) {
|
||||
// 构建本地树
|
||||
TreeDTO localTree = buildTree(rootNode, parentChildrenMap, true);
|
||||
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());
|
||||
}
|
||||
return new DualTreeResponse(localTrees, null);
|
||||
}
|
||||
|
||||
|
||||
/**********************************
|
||||
* 用途说明: 查询备份空间结构树
|
||||
* 参数说明 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 = buildTree(rootNode, parentChildrenMap, false);
|
||||
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());
|
||||
return new DualTreeResponse(localTrees, minioTrees);
|
||||
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;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 递归构建父节点树形结构(内存操作,不再查询数据库)
|
||||
*
|
||||
* @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
|
||||
*
|
||||
@ -4040,7 +4346,18 @@ public class TsFilesServiceImpl extends ServiceImpl<TsFilesMapper, TsFiles> impl
|
||||
queryWrapperSysDictionary.eq("parentcode", "compressType");
|
||||
queryWrapperSysDictionary.orderByAsc("orderno");
|
||||
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();
|
||||
// 复制公共字段
|
||||
@ -4056,7 +4373,7 @@ public class TsFilesServiceImpl extends ServiceImpl<TsFilesMapper, TsFiles> impl
|
||||
dto.setUploadTime(node.getUploadTime());
|
||||
dto.setUploader(node.getUploader());
|
||||
dto.setUpdateTime(node.getUpdateTime());
|
||||
|
||||
dto.setNumber(count);
|
||||
//查询本地
|
||||
if (isLocal) {
|
||||
String workPath = node.getWorkPath();
|
||||
@ -4069,6 +4386,9 @@ public class TsFilesServiceImpl extends ServiceImpl<TsFilesMapper, TsFiles> impl
|
||||
String path = workPath + fileNameData;
|
||||
//准备获取文件的信息
|
||||
if ("FILE".equals(node.getIsFile())) {
|
||||
// dto.setUrl(null);
|
||||
// dto.setType(null);
|
||||
|
||||
LOGGER.info("查询本地树的时候" + path);
|
||||
AbstractBaseFileService<?> fileService = storageSourceContext.getByStorageKey("local");
|
||||
FileItemResult fileItemResult = fileService.getFileItem(path);
|
||||
|
@ -59,10 +59,10 @@ public abstract class AbstractS3BaseFileService<P extends S3BaseParam> extends A
|
||||
return s3FileList(folderPath);
|
||||
}
|
||||
|
||||
// @Override
|
||||
// public List<FileItemResult> fileLists(String folderPath) {
|
||||
// return s3FileLists(folderPath);
|
||||
// }
|
||||
@Override
|
||||
public List<FileItemResult> fileLists(String folderPath) {
|
||||
return s3FileLists(folderPath);
|
||||
}
|
||||
@Override
|
||||
public List<FileItemResult> fileListData(String path, String name ) {
|
||||
return s3FileListData(path,name);
|
||||
@ -353,86 +353,87 @@ public abstract class AbstractS3BaseFileService<P extends S3BaseParam> extends A
|
||||
return path.startsWith("/") ? path : "/" + path;
|
||||
}
|
||||
//这个方法有用 获取指定路径下的所有的文件以及文件夹
|
||||
// public List<FileItemResult> s3FileLists(String path) {
|
||||
// String bucketName = param.getBucketName();
|
||||
// path = StringUtils.trimStartSlashes(path); // 去掉路径开头的斜杠
|
||||
// String fullPath = StringUtils.trimStartSlashes(StringUtils.concat(param.getBasePath(), path, ZFileConstant.PATH_SEPARATOR));
|
||||
//
|
||||
// List<FileItemResult> fileItemList = new ArrayList<>();
|
||||
//
|
||||
// // 调用递归方法获取文件列表
|
||||
// listFilesInDirectory(bucketName, fullPath, path, fileItemList);
|
||||
//
|
||||
// return fileItemList;
|
||||
// }
|
||||
//
|
||||
// private void listFilesInDirectory(String bucketName, String fullPath, String path, List<FileItemResult> fileItemList) {
|
||||
// ListObjectsRequest listObjectsRequest = new ListObjectsRequest()
|
||||
// .withBucketName(bucketName)
|
||||
// .withPrefix(fullPath) // 设置前缀为当前路径
|
||||
// .withMaxKeys(1000) // 每次最多返回 1000 个对象
|
||||
// .withDelimiter("/"); // 使用 "/" 作为分隔符
|
||||
//
|
||||
// ObjectListing objectListing = s3Client.listObjects(listObjectsRequest);
|
||||
// boolean isFirstWhile = true;
|
||||
//
|
||||
// do {
|
||||
// if (!isFirstWhile) {
|
||||
// objectListing = s3Client.listNextBatchOfObjects(objectListing); // 处理分页
|
||||
// }
|
||||
//
|
||||
// // 处理文件
|
||||
// for (S3ObjectSummary s : objectListing.getObjectSummaries()) {
|
||||
// FileItemResult fileItemResult = new FileItemResult();
|
||||
//
|
||||
// // 跳过当前目录本身
|
||||
// if (s.getKey().equals(fullPath)) {
|
||||
// continue;
|
||||
// }
|
||||
//
|
||||
// // 获取文件名并去除前导斜杠
|
||||
// String fileName = s.getKey().substring(fullPath.length());
|
||||
// if (fileName.startsWith(ZFileConstant.PATH_SEPARATOR)) {
|
||||
// fileName = fileName.substring(1); // 去掉开头的斜杠
|
||||
// }
|
||||
//
|
||||
// fileItemResult.setName(fileName);
|
||||
// fileItemResult.setSize(s.getSize());
|
||||
// fileItemResult.setTime(s.getLastModified());
|
||||
// fileItemResult.setType(FileTypeEnum.FILE);
|
||||
// fileItemResult.setPath(path); // 当前路径
|
||||
//
|
||||
// // 构造完整路径并生成下载 URL
|
||||
// String fullPathAndName = StringUtils.concat(path, fileItemResult.getName());
|
||||
// fileItemResult.setUrl(getDownloadUrl(fullPathAndName));
|
||||
//
|
||||
// fileItemList.add(fileItemResult);
|
||||
// }
|
||||
//
|
||||
// // 处理文件夹
|
||||
// for (String commonPrefix : objectListing.getCommonPrefixes()) {
|
||||
// FileItemResult fileItemResult = new FileItemResult();
|
||||
//
|
||||
// // 获取文件夹名称,去掉前导路径并修正末尾斜杠
|
||||
// String folderName = commonPrefix.substring(fullPath.length(), commonPrefix.length() - 1);
|
||||
// if (StrUtil.isEmpty(folderName) || StrUtil.equals(folderName, StringUtils.DELIMITER_STR)) {
|
||||
// continue; // 跳过无效的文件夹名称
|
||||
// }
|
||||
//
|
||||
// fileItemResult.setName(folderName);
|
||||
// fileItemResult.setType(FileTypeEnum.FOLDER);
|
||||
// fileItemResult.setPath(path); // 当前路径
|
||||
// fileItemList.add(fileItemResult);
|
||||
//
|
||||
// // 递归处理子文件夹
|
||||
// String subFolderPath = path + folderName + ZFileConstant.PATH_SEPARATOR; // 修正路径拼接
|
||||
// String subFolderFullPath = commonPrefix; // 子文件夹的完整路径
|
||||
// listFilesInDirectory(bucketName, subFolderFullPath, subFolderPath, fileItemList);
|
||||
// }
|
||||
//
|
||||
// isFirstWhile = false;
|
||||
// } while (objectListing.isTruncated()); // 处理分页
|
||||
// }
|
||||
public List<FileItemResult> s3FileLists(String path) {
|
||||
String bucketName = param.getBucketName();
|
||||
path = StringUtils.trimStartSlashes(path); // 去掉路径开头的斜杠
|
||||
String fullPath = StringUtils.trimStartSlashes(StringUtils.concat(param.getBasePath(), path, ZFileConstant.PATH_SEPARATOR));
|
||||
|
||||
List<FileItemResult> fileItemList = new ArrayList<>();
|
||||
|
||||
// 调用递归方法获取文件列表
|
||||
listFilesInDirectory(bucketName, fullPath, path, fileItemList);
|
||||
|
||||
return fileItemList;
|
||||
}
|
||||
|
||||
private void listFilesInDirectory(String bucketName, String fullPath, String path, List<FileItemResult> fileItemList) {
|
||||
ListObjectsRequest listObjectsRequest = new ListObjectsRequest()
|
||||
.withBucketName(bucketName)
|
||||
.withPrefix(fullPath) // 设置前缀为当前路径
|
||||
.withMaxKeys(1000) // 每次最多返回 1000 个对象
|
||||
.withDelimiter("/"); // 使用 "/" 作为分隔符
|
||||
|
||||
ObjectListing objectListing = s3Client.listObjects(listObjectsRequest);
|
||||
boolean isFirstWhile = true;
|
||||
|
||||
do {
|
||||
if (!isFirstWhile) {
|
||||
objectListing = s3Client.listNextBatchOfObjects(objectListing); // 处理分页
|
||||
}
|
||||
|
||||
// 处理文件
|
||||
for (S3ObjectSummary s : objectListing.getObjectSummaries()) {
|
||||
FileItemResult fileItemResult = new FileItemResult();
|
||||
|
||||
// 跳过当前目录本身
|
||||
if (s.getKey().equals(fullPath)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// 获取文件名并去除前导斜杠
|
||||
String fileName = s.getKey().substring(fullPath.length());
|
||||
if (fileName.startsWith(ZFileConstant.PATH_SEPARATOR)) {
|
||||
fileName = fileName.substring(1); // 去掉开头的斜杠
|
||||
}
|
||||
|
||||
fileItemResult.setName(fileName);
|
||||
fileItemResult.setSize(s.getSize());
|
||||
fileItemResult.setTime(s.getLastModified());
|
||||
fileItemResult.setType(FileTypeEnum.FILE);
|
||||
fileItemResult.setPath(path); // 当前路径
|
||||
|
||||
// 构造完整路径并生成下载 URL
|
||||
String fullPathAndName = StringUtils.concat(path, fileItemResult.getName());
|
||||
fileItemResult.setUrl(getDownloadUrl(fullPathAndName));
|
||||
|
||||
fileItemList.add(fileItemResult);
|
||||
}
|
||||
|
||||
// 处理文件夹
|
||||
for (String commonPrefix : objectListing.getCommonPrefixes()) {
|
||||
FileItemResult fileItemResult = new FileItemResult();
|
||||
|
||||
// 获取文件夹名称,去掉前导路径并修正末尾斜杠
|
||||
String folderName = commonPrefix.substring(fullPath.length(), commonPrefix.length() - 1);
|
||||
if (StrUtil.isEmpty(folderName) || StrUtil.equals(folderName, StringUtils.DELIMITER_STR)) {
|
||||
continue; // 跳过无效的文件夹名称
|
||||
}
|
||||
|
||||
fileItemResult.setName(folderName);
|
||||
fileItemResult.setType(FileTypeEnum.FOLDER);
|
||||
fileItemResult.setPath(path); // 当前路径
|
||||
|
||||
fileItemList.add(fileItemResult);
|
||||
|
||||
// 递归处理子文件夹
|
||||
String subFolderPath = path + folderName + ZFileConstant.PATH_SEPARATOR; // 修正路径拼接
|
||||
String subFolderFullPath = commonPrefix; // 子文件夹的完整路径
|
||||
listFilesInDirectory(bucketName, subFolderFullPath, subFolderPath, fileItemList);
|
||||
}
|
||||
|
||||
isFirstWhile = false;
|
||||
} while (objectListing.isTruncated()); // 处理分页
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
|
@ -262,17 +262,17 @@ public interface BaseFileService {
|
||||
*/
|
||||
S3Object getObject(String bucketName, String key);
|
||||
|
||||
// /***
|
||||
// * 获取指定路径下的文件及文件夹
|
||||
// *
|
||||
// * @param folderPath
|
||||
// * 文件夹路径
|
||||
// *
|
||||
// * @return 文件及文件夹列表
|
||||
// *
|
||||
// * @throws Exception 获取文件列表中出现的异常 /
|
||||
// */
|
||||
// List<FileItemResult> fileLists(String folderPath) throws Exception;
|
||||
/***
|
||||
* 获取指定路径下的文件及文件夹
|
||||
*
|
||||
* @param folderPath
|
||||
* 文件夹路径
|
||||
*
|
||||
* @return 文件及文件夹列表
|
||||
*
|
||||
* @throws Exception 获取文件列表中出现的异常 /
|
||||
*/
|
||||
List<FileItemResult> fileLists(String folderPath) throws Exception;
|
||||
|
||||
/***
|
||||
* 获取指定路径下的文件及文件夹
|
||||
|
@ -359,79 +359,82 @@ public class LocalServiceImpl extends AbstractProxyTransferService<LocalParam> {
|
||||
}
|
||||
|
||||
//以下是通过路径获取所有的文件以及文件夹
|
||||
// @Override
|
||||
// public List<FileItemResult> fileLists(String folderPath) throws Exception {
|
||||
// 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;
|
||||
// }
|
||||
@Override
|
||||
public List<FileItemResult> fileLists(String folderPath) throws Exception {
|
||||
checkPathSecurity(folderPath);
|
||||
|
||||
// private void listFilesInDirectory(File file, String folderPath, List<FileItemResult> fileItemList, boolean skipFirstFolder) throws IOException {
|
||||
// // 跳过第一个文件夹(folderPath),从它下面的内容开始处理
|
||||
// if (skipFirstFolder) {
|
||||
// // 如果当前文件是 folderPath, 直接跳过,开始处理它的子文件夹
|
||||
// if (file.isDirectory()) {
|
||||
// File[] files = file.listFiles();
|
||||
// if (files != null) {
|
||||
// for (File f : files) {
|
||||
// // 递归进入下一级文件夹,路径应该是 folderPath + 当前文件夹名
|
||||
// listFilesInDirectory(f, folderPath, fileItemList, false);
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// } else {
|
||||
// // 处理当前的文件夹或文件
|
||||
// if (file.isDirectory()) {
|
||||
// // 对于文件夹,路径是 folderPath
|
||||
// fileItemList.add(fileToFileItems(file, folderPath));
|
||||
//
|
||||
// // 递归处理当前文件夹内部的文件和文件夹
|
||||
// File[] files = file.listFiles();
|
||||
// if (files != null) {
|
||||
// for (File f : files) {
|
||||
// // 递归进入下一级文件夹,路径是 folderPath + 当前文件夹名
|
||||
// String newPath = folderPath + file.getName();
|
||||
// listFilesInDirectory(f, newPath, fileItemList, false);
|
||||
// }
|
||||
// }
|
||||
// } else {
|
||||
// // 对于文件,路径是 folderPath
|
||||
// fileItemList.add(fileToFileItems(file, folderPath));
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// //lilin增加
|
||||
// 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);
|
||||
// }
|
||||
//
|
||||
// result.setSize(file.length());
|
||||
// // 设置文件的修改时间为 Date 类型
|
||||
// result.setTime(new Date(file.lastModified()));
|
||||
//
|
||||
// return result;
|
||||
// }
|
||||
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 {
|
||||
// 跳过第一个文件夹(folderPath),从它下面的内容开始处理
|
||||
if (skipFirstFolder) {
|
||||
// 如果当前文件是 folderPath, 直接跳过,开始处理它的子文件夹
|
||||
if (file.isDirectory()) {
|
||||
File[] files = file.listFiles();
|
||||
if (files != null) {
|
||||
for (File f : files) {
|
||||
// 递归进入下一级文件夹,路径应该是 folderPath + 当前文件夹名
|
||||
listFilesInDirectory(f, folderPath, fileItemList, false);
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// 处理当前的文件夹或文件
|
||||
if (file.isDirectory()) {
|
||||
// 对于文件夹,路径是 folderPath
|
||||
fileItemList.add(fileToFileItems(file, folderPath));
|
||||
|
||||
// 递归处理当前文件夹内部的文件和文件夹
|
||||
File[] files = file.listFiles();
|
||||
if (files != null) {
|
||||
for (File f : files) {
|
||||
// 递归进入下一级文件夹,路径是 folderPath + 当前文件夹名
|
||||
String newPath = folderPath + file.getName();
|
||||
listFilesInDirectory(f, newPath, fileItemList, false);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// 对于文件,路径是 folderPath
|
||||
fileItemList.add(fileToFileItems(file, folderPath));
|
||||
}
|
||||
}
|
||||
}
|
||||
//lilin增加
|
||||
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
|
||||
|
Loading…
Reference in New Issue
Block a user