修改
This commit is contained in:
commit
307a21acac
@ -35,18 +35,14 @@ public class TaskStatusHolder {
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
// 原子性检查并标记任务开始
|
||||
public boolean startTaskIfAbsent(String key) {
|
||||
return taskStatusMap.putIfAbsent(key, "IN_PROGRESS") == null;
|
||||
}
|
||||
|
||||
// 标记任务结束
|
||||
public void finishTask(String key) {
|
||||
taskStatusMap.remove(key);
|
||||
}
|
||||
|
||||
// 获取任务状态
|
||||
public String getStatus(String key) {
|
||||
return taskStatusMap.getOrDefault(key, "TASK_NOT_FOUND");
|
||||
|
@ -65,13 +65,15 @@ public class TsFilesController {
|
||||
public ResponseResult getTsFilesPage(String id, String fileName, String startDate, String endDate, String keywords, String nodeId, String taskId, String childNode, Page<TsFiles> page) throws Exception {
|
||||
//分页查询
|
||||
int currentPage = (int) page.getCurrent();
|
||||
// 先尝试从缓存获取
|
||||
if(!StrUtil.isEmpty(id)){
|
||||
IPage<TsFiles> cachedPage = tsFilesService.getCachedTsFilesPage(taskId, nodeId, currentPage,id);
|
||||
// 先尝试从缓存获取 如果搜索条件为空 从Redis获取
|
||||
if(StrUtil.isBlank(fileName)&&StrUtil.isBlank(keywords) &&StrUtil.isBlank(startDate) &&StrUtil.isBlank(endDate)) {
|
||||
if (!StrUtil.isEmpty(id)) {
|
||||
IPage<TsFiles> cachedPage = tsFilesService.getCachedTsFilesPage(taskId, nodeId, currentPage, id);
|
||||
if (cachedPage != null) {
|
||||
return ResponseResult.successData(cachedPage);
|
||||
}
|
||||
}
|
||||
}
|
||||
Page<TsFiles> tsfilesPage = tsFilesService.getTsFilesPage(id, fileName, startDate, endDate, keywords, nodeId, taskId, fileName, childNode, page);
|
||||
return ResponseResult.successData(tsfilesPage);
|
||||
}
|
||||
@ -238,8 +240,6 @@ public class TsFilesController {
|
||||
if (StrUtil.isBlank(id)) {
|
||||
return ResponseResult.error("参数为空");
|
||||
}
|
||||
|
||||
|
||||
return ResponseResult.success(tsFilesService.decompressionFolder(id, decompressionPath, parentId, path));
|
||||
} catch (Exception e) {
|
||||
System.out.print("解压缩异常原因" + e);
|
||||
@ -619,14 +619,14 @@ public class TsFilesController {
|
||||
@Log(module = "实验数据管理", value = "文件自动备份!")
|
||||
@PostMapping("/automaticFileBackupByIds")
|
||||
@ApiOperation("自动备份本地文件到备份空间通过ID")
|
||||
public ResponseResult automaticFileBackupByIds(String id) throws IOException {
|
||||
public ResponseResult automaticFileBackupByIds(String id,String taskId, String nodeId) throws IOException {
|
||||
if (StrUtil.isEmpty(id)) {
|
||||
return ResponseResult.error("参数为空");
|
||||
}
|
||||
List<String> dataset = StrUtil.split(id, ",");
|
||||
|
||||
// 生成唯一Key
|
||||
String asyncKey = taskStatusHolder.generateKeybyId(dataset);
|
||||
String asyncKey = taskStatusHolder.generateKey(taskId, nodeId);
|
||||
|
||||
// 检查任务是否已存在
|
||||
String existingStatus = taskStatusHolder.getStatus(asyncKey);
|
||||
@ -638,7 +638,7 @@ public class TsFilesController {
|
||||
// 原子性启动新任务
|
||||
if (taskStatusHolder.startTaskIfAbsent(asyncKey)) {
|
||||
// 直接异步执行并推送结果
|
||||
tsFilesService.automaticFileBackupAsyncByIds(dataset);
|
||||
tsFilesService.automaticFileBackupAsyncByIds(dataset,taskId,nodeId);
|
||||
return ResponseResult.success("任务开始处理!");
|
||||
} else {
|
||||
return ResponseResult.success("任务已由其他请求启动");
|
||||
|
@ -4,6 +4,7 @@ package com.yfd.platform.modules.experimentalData.controller;
|
||||
import cn.hutool.core.util.ObjUtil;
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
import cn.hutool.json.JSONObject;
|
||||
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
|
||||
import com.yfd.platform.annotation.Log;
|
||||
import com.yfd.platform.component.TaskStatusHolder;
|
||||
import com.yfd.platform.config.ResponseResult;
|
||||
@ -183,4 +184,28 @@ public class TsNodesController {
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**********************************
|
||||
* 用途说明: 查询可不可以初始化试验任务扫描
|
||||
* 参数说明 taskId 试验任务ID
|
||||
* 返回值说明: com.yfd.platform.config.ResponseResult
|
||||
***********************************/
|
||||
@Log(module = "查询可不可以初始化试验任务扫描", value = "查询可不可以初始化试验任务扫描!")
|
||||
@PostMapping("/selectTsNodesByTskeId")
|
||||
@ApiOperation("查询可不可以初始化试验任务扫描")
|
||||
@PreAuthorize("@el.check('del:tsnodes')")
|
||||
public ResponseResult selectTsNodesByTskeId( String taskId) {
|
||||
if (StrUtil.isBlank(taskId)) {
|
||||
return ResponseResult.error("参数为空");
|
||||
}
|
||||
List<TsNodes> tsNodesList = tsNodesService.list(new QueryWrapper<TsNodes>().eq("task_id", taskId));
|
||||
//如果节点不为空 就不能初始化了
|
||||
if (tsNodesList.size()>0) {
|
||||
return ResponseResult.success("该项目已经初始化完成,局部更新请选择节点上传文件!");
|
||||
} else {
|
||||
return ResponseResult.success("可以初始化!");
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -247,7 +247,7 @@ public interface ITsFilesService extends IService<TsFiles> {
|
||||
|
||||
Object compareMd5List(List<String> dataset, String nodeId, String taskId);
|
||||
|
||||
void automaticFileBackupAsyncByIds(List<String> dataset) throws IOException;
|
||||
void automaticFileBackupAsyncByIds(List<String> dataset,String taskId, String nodeId) throws IOException;
|
||||
|
||||
IPage<TsFiles> getCachedTsFilesPage(String taskId, String nodeId, int currentPage,String id);
|
||||
}
|
||||
|
@ -267,15 +267,14 @@ public class TsFilesServiceImpl extends ServiceImpl<TsFilesMapper, TsFiles> impl
|
||||
|
||||
tsFilesPage.setRecords(records); // 同步到 tsFilesPage
|
||||
int currentPage = (int) page.getCurrent();
|
||||
// 如果是前五页,将结果存入Redis(有效期建议30分钟)
|
||||
// 如果是前五页,将结果存入Redis(有效期建议30分钟)如果搜索条件为空 从Redis获取
|
||||
if (StrUtil.isBlank(fileName) && StrUtil.isBlank(keywords) && StrUtil.isBlank(startDate) && StrUtil.isBlank(endDate)) {
|
||||
if (!StrUtil.isEmpty(id)) {
|
||||
if (currentPage >= 1 && currentPage <= 5) {
|
||||
String redisKey = "tsfiles_" + taskId + "_" + nodeId + "_parentId" + id + "_page_" + currentPage + "";
|
||||
redisTemplate.opsForValue().set(redisKey, tsFilesPage, 2, TimeUnit.HOURS);
|
||||
}
|
||||
} else {
|
||||
String redisKey = "tsfiles_" + taskId + "_" + nodeId + "_page_" + currentPage;
|
||||
redisTemplate.delete(redisKey);
|
||||
}
|
||||
}
|
||||
return tsFilesPage;
|
||||
|
||||
@ -292,26 +291,49 @@ public class TsFilesServiceImpl extends ServiceImpl<TsFilesMapper, TsFiles> impl
|
||||
@Override
|
||||
public IPage<TsFiles> getCachedTsFilesPage(String taskId, String nodeId, int currentPage, String id) {
|
||||
String redisKey = "tsfiles_" + taskId + "_" + nodeId + "_parentId" + id + "_page_" + currentPage;
|
||||
|
||||
|
||||
Object data = redisTemplate.opsForValue().get(redisKey);
|
||||
|
||||
try {
|
||||
if (data instanceof IPage<?>) {
|
||||
// 由于启用了类型信息,可以直接强制转换
|
||||
@SuppressWarnings("unchecked")
|
||||
IPage<TsFiles> page = (IPage<TsFiles>) data;
|
||||
// 检查 records 是否已正确反序列化
|
||||
if (page.getRecords() != null && !page.getRecords().isEmpty()
|
||||
&& page.getRecords().get(0) instanceof TsFiles) {
|
||||
|
||||
// 类型校验
|
||||
if (isValidPage(page)) {
|
||||
return page;
|
||||
} else {
|
||||
// 处理可能的反序列化异常
|
||||
throw new IllegalStateException("反序列化失败,records 类型不正确");
|
||||
}
|
||||
}
|
||||
return null;
|
||||
} catch (Exception e) {
|
||||
// 记录异常日志(关键!)
|
||||
LOGGER.error("反序列化失败,删除缓存: {}", redisKey, e);
|
||||
|
||||
// 异步删除缓存,避免阻塞主流程
|
||||
CompletableFuture.runAsync(() -> redisTemplate.delete(redisKey));
|
||||
}
|
||||
|
||||
return null; // 或返回空分页对象 new Page<>(0)
|
||||
|
||||
// if (data instanceof IPage<?>) {
|
||||
// // 由于启用了类型信息,可以直接强制转换
|
||||
// @SuppressWarnings("unchecked")
|
||||
// IPage<TsFiles> page = (IPage<TsFiles>) data;
|
||||
// // 检查 records 是否已正确反序列化
|
||||
// if (page.getRecords() != null && !page.getRecords().isEmpty()
|
||||
// && page.getRecords().get(0) instanceof TsFiles) {
|
||||
// return page;
|
||||
// } else {
|
||||
// // 处理可能的反序列化异常
|
||||
// throw new IllegalStateException("反序列化失败,records 类型不正确");
|
||||
// }
|
||||
// }
|
||||
// return null;
|
||||
}
|
||||
|
||||
|
||||
private boolean isValidPage(IPage<TsFiles> page) {
|
||||
return page.getRecords() != null
|
||||
&& !page.getRecords().isEmpty()
|
||||
&& page.getRecords().get(0) instanceof TsFiles;
|
||||
}
|
||||
|
||||
public boolean hasValidExtension(String name, List<SysDictionaryItems> sysDictionaryItems) {
|
||||
// 如果传入的文件名为空,返回 false
|
||||
@ -417,8 +439,6 @@ public class TsFilesServiceImpl extends ServiceImpl<TsFilesMapper, TsFiles> impl
|
||||
//todo 新增成功以后 删除redis
|
||||
for (int page = 1; page <= 5; page++) {
|
||||
String redisKey = "tsfiles_" + tsFiles.getTaskId() + "_" + tsFiles.getNodeId() + "_parentId" + tsFiles.getParentId() + "_page_" + page;
|
||||
|
||||
|
||||
redisTemplate.delete(redisKey);
|
||||
}
|
||||
LOGGER.info("已清理缓存:taskid={}, node={}, pages=1-5", tsFiles.getTaskId(), tsFiles.getNodeId());
|
||||
@ -658,7 +678,7 @@ public class TsFilesServiceImpl extends ServiceImpl<TsFilesMapper, TsFiles> impl
|
||||
@Transactional(rollbackFor = Exception.class)// 添加事务注解,遇到异常时回滚
|
||||
public ResponseResult updateTsFiles(TsFiles tsFiles) {
|
||||
|
||||
//todo 新增成功以后 删除redis
|
||||
//todo 修改成功以后 删除redis
|
||||
for (int page = 1; page <= 5; page++) {
|
||||
String redisKey = "tsfiles_" + tsFiles.getTaskId() + "_" + tsFiles.getNodeId() + "_parentId" + tsFiles.getParentId() + "_page_" + page;
|
||||
redisTemplate.delete(redisKey);
|
||||
@ -939,10 +959,19 @@ public class TsFilesServiceImpl extends ServiceImpl<TsFilesMapper, TsFiles> impl
|
||||
public String deleteTsFilesByIds(List<String> dataset, String type) {
|
||||
List<TsFiles> filesList = tsFilesMapper.selectBatchIds(dataset);
|
||||
|
||||
//todo 删除的时候成功以后 删除redis
|
||||
for (int page = 1; page <= 5; page++) {
|
||||
String redisKey = "tsfiles_" + filesList.get(0).getTaskId() + "_" + filesList.get(0).getNodeId() + "_parentId" + filesList.get(0).getParentId() + "_page_" + page;
|
||||
redisTemplate.delete(redisKey);
|
||||
}
|
||||
LOGGER.info("已清理缓存:taskid={}, node={}, pages=1-5", filesList.get(0).getTaskId(), filesList.get(0).getNodeId());
|
||||
|
||||
|
||||
int LocalSuccessCount = 0, LocalFailCount = 0, Localtotal = CollUtil.size(dataset);
|
||||
//Todo 最直接的办法 循环出来 一条一条删除
|
||||
for (TsFiles files : filesList) {
|
||||
|
||||
|
||||
//判断是文件还是文件夹
|
||||
if ("FOLDER".equals(files.getIsFile())) {
|
||||
//如果是文件夹
|
||||
@ -1233,6 +1262,15 @@ public class TsFilesServiceImpl extends ServiceImpl<TsFilesMapper, TsFiles> impl
|
||||
try {
|
||||
String finalParentId = ensureFullPathExists(compressedPath, filesList.get(0).getNodeId(), filesList.get(0).getTaskId(), path);
|
||||
parentId = finalParentId;
|
||||
LOGGER.info("压缩的时候删除Redis");
|
||||
//todo 压缩的时候删除Redis
|
||||
if (!parentId.equals("00")) {
|
||||
for (int page = 1; page <= 5; page++) {
|
||||
String redisKey = "tsfiles_" + filesList.get(0).getTaskId() + "_" + filesList.get(0).getNodeId() + "_parentId" + parentId + "_page_" + page;
|
||||
redisTemplate.delete(redisKey);
|
||||
}
|
||||
}
|
||||
|
||||
LOGGER.info("路径已全部存在,最终目录ID: {}", finalParentId);
|
||||
} catch (RuntimeException e) {
|
||||
LOGGER.error("路径创建失败: {}", e.getMessage());
|
||||
@ -1840,6 +1878,16 @@ public class TsFilesServiceImpl extends ServiceImpl<TsFilesMapper, TsFiles> impl
|
||||
try {
|
||||
String finalParentId = ensureFullPathExists(decompressionPath, zipFileRecord.getNodeId(), zipFileRecord.getTaskId(), path);
|
||||
parentId = finalParentId;
|
||||
|
||||
LOGGER.info("解压缩的时候删除Redis");
|
||||
//todo 解压缩的时候删除Redis
|
||||
if (!parentId.equals("00")) {
|
||||
for (int page = 1; page <= 5; page++) {
|
||||
String redisKey = "tsfiles_" + zipFileRecord.getTaskId() + "_" + zipFileRecord.getNodeId() + "_parentId" + parentId + "_page_" + page;
|
||||
redisTemplate.delete(redisKey);
|
||||
}
|
||||
}
|
||||
|
||||
LOGGER.info("路径已全部存在,最终目录ID: {}", finalParentId);
|
||||
} catch (RuntimeException e) {
|
||||
LOGGER.error("路径创建失败: {}", e.getMessage());
|
||||
@ -1910,7 +1958,7 @@ public class TsFilesServiceImpl extends ServiceImpl<TsFilesMapper, TsFiles> impl
|
||||
TsFiles fileRecord = createFileRecord(
|
||||
file.getName(),
|
||||
parentId,
|
||||
buildFolderPath(decompressionPath),
|
||||
buildFolderPath(extractPath),
|
||||
zipFileRecord.getTaskId(),
|
||||
zipFileRecord.getNodeId(),
|
||||
zipFileRecord.getUploader(),
|
||||
@ -3375,22 +3423,22 @@ public class TsFilesServiceImpl extends ServiceImpl<TsFilesMapper, TsFiles> impl
|
||||
String asyncKey = taskStatusHolder.generateKey(taskId, nodeId);
|
||||
// 无论成功失败都标记完成
|
||||
taskStatusHolder.finishTask(asyncKey);
|
||||
WebSocketServer.sendMessageTo("文件自动备份完成", "backups");
|
||||
WebSocketServer.sendMessageTo("文件自动备份完成", "taskId_" + taskId + "_" + "nodeId_" + nodeId);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
@Async("asyncExecutor")
|
||||
public void automaticFileBackupAsyncByIds(List<String> dataset) throws IOException {
|
||||
public void automaticFileBackupAsyncByIds(List<String> dataset, String taskId, String nodeId) throws IOException {
|
||||
try {
|
||||
// 执行实际备份逻辑
|
||||
this.automaticFileBackupByIds(dataset);
|
||||
} finally {
|
||||
// 生成唯一Key
|
||||
String asyncKey = taskStatusHolder.generateKeybyId(dataset);
|
||||
String asyncKey = taskStatusHolder.generateKey(taskId, nodeId);
|
||||
// 无论成功失败都标记完成
|
||||
taskStatusHolder.finishTask(asyncKey);
|
||||
WebSocketServer.sendMessageTo("文件自动备份完成", "backups");
|
||||
WebSocketServer.sendMessageTo("文件自动备份完成", "taskId_" + taskId + "_" + "nodeId_" + nodeId);
|
||||
}
|
||||
}
|
||||
|
||||
@ -3891,6 +3939,16 @@ public class TsFilesServiceImpl extends ServiceImpl<TsFilesMapper, TsFiles> impl
|
||||
*/
|
||||
private void updateDatabase(String parentId, String oldpaths, String fileName,
|
||||
String newPath, String targetFileName, String type) {
|
||||
TsFiles tsFilesData = tsFilesMapper.selectById(parentId);
|
||||
LOGGER.info("移动的时候删除Redis");
|
||||
//todo 移动的时候成功以后 删除redis
|
||||
if (!parentId.equals("00")) {
|
||||
for (int page = 1; page <= 5; page++) {
|
||||
String redisKey = "tsfiles_" + tsFilesData.getTaskId() + "_" + tsFilesData.getNodeId() + "_parentId" + parentId + "_page_" + page;
|
||||
redisTemplate.delete(redisKey);
|
||||
}
|
||||
LOGGER.info("已清理缓存:taskid={}, node={}, pages=1-5", tsFilesData.getTaskId(), tsFilesData.getNodeId());
|
||||
}
|
||||
// 1. 构建完整路径
|
||||
String oldWorkPath = oldpaths.endsWith("/") ? oldpaths : oldpaths + "/";
|
||||
String newWorkPath = newPath.endsWith("/") ? newPath : newPath + "/";
|
||||
@ -4127,6 +4185,17 @@ public class TsFilesServiceImpl extends ServiceImpl<TsFilesMapper, TsFiles> impl
|
||||
*/
|
||||
private void insertDatabaseRecord(String parentId, String oldpaths, String fileName,
|
||||
String newPath, String targetFileName, String type) {
|
||||
|
||||
TsFiles tsFilesData = tsFilesMapper.selectById(parentId);
|
||||
LOGGER.info("复制的时候删除Redis");
|
||||
//todo 复制的时候成功以后 删除redis
|
||||
if (!parentId.equals("00")) {
|
||||
for (int page = 1; page <= 5; page++) {
|
||||
String redisKey = "tsfiles_" + tsFilesData.getTaskId() + "_" + tsFilesData.getNodeId() + "_parentId" + parentId + "_page_" + page;
|
||||
redisTemplate.delete(redisKey);
|
||||
}
|
||||
LOGGER.info("已清理缓存:taskid={}, node={}, pages=1-5", tsFilesData.getTaskId(), tsFilesData.getNodeId());
|
||||
}
|
||||
// 获取用户信息
|
||||
// 获取当前用户和时间
|
||||
UsernamePasswordAuthenticationToken authentication =
|
||||
|
@ -477,11 +477,23 @@ public class TsNodesServiceImpl extends ServiceImpl<TsNodesMapper, TsNodes> impl
|
||||
|
||||
//批量修改
|
||||
LambdaUpdateWrapper<TsFiles> updateWrapper1 = new LambdaUpdateWrapper<>();
|
||||
updateWrapper1.in(TsFiles::getId,dataset).isNotNull(TsFiles::getBackupPath).ne(TsFiles::getBackupPath,"").set(TsFiles::getWorkPath, "");
|
||||
updateWrapper1.in(TsFiles::getId, dataset).set(TsFiles::getWorkPath, "");
|
||||
tsFilesMapper.update(null, updateWrapper1);
|
||||
//批量删除
|
||||
// LambdaQueryWrapper<TsFiles> deleteWrapper = new LambdaQueryWrapper<>();
|
||||
// deleteWrapper.in(TsFiles::getId, dataset).isNull(TsFiles::getBackupPath).eq(TsFiles::getBackupPath, "").isNull(TsFiles::getWorkPath).eq(TsFiles::getWorkPath, "");
|
||||
// tsFilesMapper.delete(deleteWrapper);
|
||||
//
|
||||
// LambdaQueryWrapper<TsFiles> deleteWrapper = new LambdaQueryWrapper<>();
|
||||
// deleteWrapper.in(TsFiles::getId, dataset)
|
||||
// .and(wrapper -> wrapper.isNull(TsFiles::getBackupPath).or().eq(TsFiles::getBackupPath, ""))
|
||||
// .and(wrapper -> wrapper.isNull(TsFiles::getWorkPath).or().eq(TsFiles::getWorkPath, ""));
|
||||
// tsFilesMapper.delete(deleteWrapper);
|
||||
|
||||
LambdaQueryWrapper<TsFiles> deleteWrapper = new LambdaQueryWrapper<>();
|
||||
deleteWrapper.in(TsFiles::getId,dataset).isNull(TsFiles::getBackupPath).eq(TsFiles::getBackupPath,"").isNull(TsFiles::getWorkPath).eq(TsFiles::getWorkPath,"");
|
||||
deleteWrapper.in(TsFiles::getId, dataset)
|
||||
.and(wrapper -> wrapper.isNull(TsFiles::getBackupPath).or().eq(TsFiles::getBackupPath, ""))
|
||||
.and(wrapper -> wrapper.isNull(TsFiles::getWorkPath).or().eq(TsFiles::getWorkPath, ""));
|
||||
tsFilesMapper.delete(deleteWrapper);
|
||||
|
||||
// //批量修改TsFiles表结构
|
||||
@ -777,17 +789,13 @@ public class TsNodesServiceImpl extends ServiceImpl<TsNodesMapper, TsNodes> impl
|
||||
LocalDateTime now = LocalDateTime.now();
|
||||
// 转换为 Timestamp
|
||||
Timestamp currentTime = Timestamp.valueOf(now);
|
||||
|
||||
|
||||
// 查询本地文件路径根目录(如 E:\yun)
|
||||
QueryWrapper<StorageSourceConfig> queryWrapper = new QueryWrapper<>();
|
||||
queryWrapper.eq("name", "filePath");
|
||||
queryWrapper.eq("type", "local");
|
||||
StorageSourceConfig storageSourceConfig = storageSourceConfigMapper.selectOne(queryWrapper);
|
||||
|
||||
//获取文件列表 这个地方path+name
|
||||
File projectDir = new File(storageSourceConfig.getValue() + path + nodeName);
|
||||
|
||||
// 获取所有子目录
|
||||
List<File> allSubDirs = new ArrayList<>();
|
||||
getAllSubDirectories(projectDir, allSubDirs);
|
||||
@ -899,88 +907,6 @@ public class TsNodesServiceImpl extends ServiceImpl<TsNodesMapper, TsNodes> impl
|
||||
long costTimeFiles = endTimeFiles - startTimeFiles;
|
||||
// 打印日志
|
||||
LOGGER.info("文件表中的节点ID更新完成,影响 {} 行,总耗时 {} 毫秒", affectedLevelFilesRows, costTimeFiles);
|
||||
|
||||
|
||||
// //获取文件列表
|
||||
// String absolutePath =path + "/" + nodeName + "/";
|
||||
// //获取当前登录用户 上传人是当前登录人
|
||||
// UsernamePasswordAuthenticationToken authentication =
|
||||
// (UsernamePasswordAuthenticationToken) SecurityContextHolder.getContext().getAuthentication();
|
||||
// LoginUser loginuser = null;
|
||||
// if (authentication != null) {
|
||||
// loginuser = (LoginUser) authentication.getPrincipal();
|
||||
// }
|
||||
// //登录人
|
||||
// String uploader = null;
|
||||
// if (loginuser != null) {
|
||||
// uploader = loginuser.getUsername();
|
||||
// }
|
||||
// // 设置当前时间
|
||||
// LocalDateTime now = LocalDateTime.now();
|
||||
// // 转换为 Timestamp
|
||||
// Timestamp currentTime = Timestamp.valueOf(now);
|
||||
//
|
||||
//
|
||||
//
|
||||
//
|
||||
//
|
||||
// //获取文件列表
|
||||
// FileListRequest fileListRequest = buildFileRequest(absolutePath);
|
||||
// String storageKey = fileListRequest.getStorageKey();
|
||||
// Integer storageId = storageSourceService.findIdByKey(storageKey);
|
||||
// if (storageId == null) {
|
||||
// throw new InvalidStorageSourceException("通过存储源 key 未找到存储源, key: " + storageKey);
|
||||
// }
|
||||
// // 处理请求参数默认值
|
||||
// fileListRequest.handleDefaultValue();
|
||||
// AbstractBaseFileService<?> fileService = storageSourceContext.getByStorageId(storageId);
|
||||
// //todo 首先获取两个集合 对比出数据库中没有的文件夹以及文件,递归增加
|
||||
// List<FileItemResult> fileItemList = fileService.fileList(fileListRequest.getPath());
|
||||
//
|
||||
// for (FileItemResult item : fileItemList) {
|
||||
// //思路就是 如果是文件夹 就查询一下 没有就新增, 新的的时候递归往下走
|
||||
// if (item.getType() == FileTypeEnum.FOLDER) {
|
||||
// //先查询有没有 如果没有就新增 条件 节点ID 任务ID 上级ID 工作空间路径 文件名称
|
||||
// LambdaQueryWrapper<TsFiles> queryWrapper1 = new LambdaQueryWrapper<>();
|
||||
// queryWrapper1.eq(TsFiles::getTaskId, taskId);
|
||||
// queryWrapper1.eq(TsFiles::getNodeId, nodeId);
|
||||
// queryWrapper1.eq(TsFiles::getParentId, parentId);
|
||||
// queryWrapper1.eq(TsFiles::getFileName, item.getName());
|
||||
// queryWrapper1.eq(TsFiles::getWorkPath, item.getPath());
|
||||
// TsFiles tsFiles = tsFilesMapper.selectOne(queryWrapper1);
|
||||
// //如果没有 新增 并且递归
|
||||
// if (tsFiles == null) {
|
||||
// //保存文件
|
||||
// TsFiles tsFilesData = savetsFiles(taskId, nodeId, item.getName(), item.getPath(), parentId, "FOLDER", String.valueOf(item.getSize()));
|
||||
// otherLevelsData(taskId, nodeId, item.getName(), item.getPath(), tsFilesData.getId());
|
||||
//
|
||||
// } else {
|
||||
// otherLevelsData(taskId, nodeId, item.getName(), item.getPath(), tsFiles.getId());
|
||||
// }
|
||||
// } else {
|
||||
// //todo 如果是文件 直接新增就可以了 不需要其他的操作
|
||||
// //先查询有没有 如果没有就新增 条件 节点ID 任务ID 上级ID 工作空间路径 文件名称
|
||||
// LambdaQueryWrapper<TsFiles> queryWrapper2 = new LambdaQueryWrapper<>();
|
||||
// queryWrapper2.eq(TsFiles::getTaskId, taskId);
|
||||
// queryWrapper2.eq(TsFiles::getNodeId, nodeId);
|
||||
// queryWrapper2.eq(TsFiles::getParentId, parentId);
|
||||
// queryWrapper2.eq(TsFiles::getFileName, item.getName());
|
||||
// queryWrapper2.eq(TsFiles::getWorkPath, item.getPath());
|
||||
// TsFiles tsFiles = tsFilesMapper.selectOne(queryWrapper2);
|
||||
// if (tsFiles == null) {
|
||||
//
|
||||
// // 获取文件大小(字节)
|
||||
// long fileSizeInBytes = item.getSize();
|
||||
// // 转换为 MB 并保留两位小数
|
||||
// double fileSizeInMB = fileSizeInBytes / (1024.0 * 1024.0);
|
||||
// String fileSizeFormatted = String.format("%.2f", fileSizeInMB); // 保留两位小数
|
||||
//
|
||||
// //保存文件信息
|
||||
// TsFiles tsFilesData = savetsFiles(taskId, nodeId, item.getName(), item.getPath(), parentId, "FILE", fileSizeFormatted);
|
||||
// LOGGER.info("保存文件信息:{}", item.getPath() + item.getName());
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -56,11 +56,13 @@ public class FilesController {
|
||||
public ResponseResult getFilesPage(String fileName, String startDate, String endDate, String keywords, String nodeId,String projectId, Page<Files> page) throws Exception {
|
||||
//分页查询
|
||||
int currentPage = (int) page.getCurrent();
|
||||
// 先尝试从缓存获取
|
||||
IPage<Files> cachedFilesPage = filesService.getCachedFilesPage(projectId, nodeId,currentPage );
|
||||
// 先尝试从缓存获取 如果搜索条件为空 从Redis获取
|
||||
if(StrUtil.isBlank(fileName)&&StrUtil.isBlank(keywords) &&StrUtil.isBlank(startDate) &&StrUtil.isBlank(endDate)){
|
||||
IPage<Files> cachedFilesPage = filesService.getCachedFilesPage(projectId, nodeId,currentPage);
|
||||
if (cachedFilesPage != null){
|
||||
return ResponseResult.successData(cachedFilesPage);
|
||||
}
|
||||
}
|
||||
|
||||
Page<Files> filesPage = filesService.getFilesPage(fileName, startDate, endDate, keywords, nodeId, projectId, fileName, page);
|
||||
return ResponseResult.successData(filesPage);
|
||||
@ -71,6 +73,8 @@ public class FilesController {
|
||||
* 用途说明:新增专项文档管理-文档内容
|
||||
* 参数说明
|
||||
* Files 文档内容
|
||||
* sourcePath 源路径
|
||||
* targetPath 目标路径
|
||||
* 返回值说明: com.yfd.platform.config.ResponseResult 返回新增成功或者失败
|
||||
***********************************/
|
||||
@Log(module = "专项文档管理", value = "新增专项文档管理文档内容!")
|
||||
@ -78,7 +82,7 @@ public class FilesController {
|
||||
@ApiOperation("新增专项文档管理文档内容")
|
||||
@ResponseBody
|
||||
@PreAuthorize("@el.check('add:files')")
|
||||
public ResponseResult addFiles(@RequestBody Files files) {
|
||||
public ResponseResult addFiles(@RequestBody Files files) throws Exception {
|
||||
//对象不能为空
|
||||
if (ObjUtil.isEmpty(files)) {
|
||||
return ResponseResult.error("参数为空");
|
||||
|
@ -5,10 +5,12 @@ import cn.hutool.core.util.ObjUtil;
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
import cn.hutool.json.JSONArray;
|
||||
import cn.hutool.json.JSONObject;
|
||||
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
|
||||
import com.yfd.platform.annotation.Log;
|
||||
import com.yfd.platform.component.TaskStatusHolder;
|
||||
import com.yfd.platform.component.WebSocketServer;
|
||||
import com.yfd.platform.config.ResponseResult;
|
||||
import com.yfd.platform.modules.experimentalData.domain.TsNodes;
|
||||
import com.yfd.platform.modules.specialDocument.domain.Nodes;
|
||||
import com.yfd.platform.modules.specialDocument.service.INodesService;
|
||||
import io.swagger.annotations.ApiOperation;
|
||||
@ -246,4 +248,25 @@ public class NodesController {
|
||||
}
|
||||
|
||||
|
||||
/**********************************
|
||||
* 用途说明: 查询可不可以初始化专项文档扫描
|
||||
* 参数说明 projectId 所属项目ID
|
||||
* 返回值说明: com.yfd.platform.config.ResponseResult
|
||||
***********************************/
|
||||
@Log(module = "查询可不可以初始化专项文档扫描", value = "查询可不可以初始化专项文档扫描!")
|
||||
@PostMapping("/selectNodesByProjectId")
|
||||
@ApiOperation("查询可不可以初始化专项文档扫描")
|
||||
public ResponseResult selectNodesByProjectId( String projectId) {
|
||||
if (StrUtil.isBlank(projectId)) {
|
||||
return ResponseResult.error("参数为空");
|
||||
}
|
||||
List<Nodes> nodesList = nodesService.list(new QueryWrapper<Nodes>().eq("project_id", projectId));
|
||||
//如果节点不为空 就不能初始化了
|
||||
if (nodesList.size()>0) {
|
||||
return ResponseResult.success("该项目已经初始化完成,局部更新请选择节点上传文件!");
|
||||
} else {
|
||||
return ResponseResult.success("可以初始化!");
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -111,4 +111,16 @@ public class Files implements Serializable {
|
||||
@TableField(exist = false)
|
||||
private String type;
|
||||
|
||||
/**
|
||||
* 源路径:TODO 增加用于前端展示
|
||||
*/
|
||||
@TableField(exist = false)
|
||||
private String sourcePath;
|
||||
|
||||
/**
|
||||
* 目标路径:TODO 增加用于前端展示
|
||||
*/
|
||||
@TableField(exist = false)
|
||||
private String targetPath;
|
||||
|
||||
}
|
||||
|
@ -39,9 +39,11 @@ public interface IFilesService extends IService<Files> {
|
||||
* 用途说明:新增专项文档管理-文档内容
|
||||
* 参数说明
|
||||
* Files 文档内容
|
||||
* sourcePath 源路径
|
||||
* targetPath 目标路径
|
||||
* 返回值说明: com.yfd.platform.config.ResponseResult 返回新增成功或者失败
|
||||
***********************************/
|
||||
ResponseResult addFiles(Files files);
|
||||
ResponseResult addFiles(Files files) throws Exception;
|
||||
|
||||
/**********************************
|
||||
* 用途说明: 修改专项文档管理-文档内容
|
||||
|
@ -3,6 +3,8 @@ package com.yfd.platform.modules.specialDocument.service.impl;
|
||||
import cn.hutool.core.collection.CollUtil;
|
||||
import cn.hutool.core.date.DateTime;
|
||||
import cn.hutool.core.date.DateUtil;
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
import cn.hutool.json.JSONObject;
|
||||
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||||
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
|
||||
import com.baomidou.mybatisplus.core.metadata.IPage;
|
||||
@ -20,6 +22,8 @@ import com.yfd.platform.modules.storage.chain.FileChain;
|
||||
import com.yfd.platform.modules.storage.chain.FileContext;
|
||||
import com.yfd.platform.modules.storage.context.StorageSourceContext;
|
||||
import com.yfd.platform.modules.storage.controller.file.FileController;
|
||||
import com.yfd.platform.modules.storage.mapper.StorageSourceConfigMapper;
|
||||
import com.yfd.platform.modules.storage.model.entity.StorageSourceConfig;
|
||||
import com.yfd.platform.modules.storage.model.enums.FileTypeEnum;
|
||||
import com.yfd.platform.modules.storage.model.request.BatchDeleteRequest;
|
||||
import com.yfd.platform.modules.storage.model.request.RenameFileRequest;
|
||||
@ -30,6 +34,10 @@ import com.yfd.platform.modules.storage.service.base.AbstractBaseFileService;
|
||||
import com.yfd.platform.system.domain.LoginUser;
|
||||
import com.yfd.platform.utils.StringUtils;
|
||||
import io.netty.channel.ChannelInboundHandlerAdapter;
|
||||
import org.apache.commons.codec.binary.Hex;
|
||||
import org.apache.commons.io.FileUtils;
|
||||
import org.apache.commons.io.FilenameUtils;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
@ -41,8 +49,17 @@ import org.springframework.transaction.annotation.Transactional;
|
||||
import com.fasterxml.jackson.core.type.TypeReference;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.nio.file.Path;
|
||||
import java.nio.file.Paths;
|
||||
import java.security.MessageDigest;
|
||||
import java.security.NoSuchAlgorithmException;
|
||||
import java.sql.Timestamp;
|
||||
import java.time.LocalDateTime;
|
||||
import java.time.format.DateTimeFormatter;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
@ -82,6 +99,9 @@ public class FilesServiceImpl extends ServiceImpl<FilesMapper, Files> implements
|
||||
@Autowired
|
||||
private RedisTemplate<String, Object> redisTemplate;
|
||||
|
||||
@Resource
|
||||
private StorageSourceConfigMapper storageSourceConfigMapper;
|
||||
|
||||
|
||||
/**********************************
|
||||
* 用途说明: 分页查询专项文档管理-文档内容
|
||||
@ -189,10 +209,12 @@ public class FilesServiceImpl extends ServiceImpl<FilesMapper, Files> implements
|
||||
filesPage.setRecords(records);
|
||||
int currentPage = (int) page.getCurrent();
|
||||
// 如果是前五页,将结果存入Redis(有效期建议30分钟)
|
||||
if (StrUtil.isBlank(fileName) && StrUtil.isBlank(keywords) && StrUtil.isBlank(startDate) && StrUtil.isBlank(endDate)) {
|
||||
if (currentPage >= 1 && currentPage <= 5) {
|
||||
String redisKey = "sdfiles_" + projectId + "_" + nodeId + "_page_" + currentPage;
|
||||
redisTemplate.opsForValue().set(redisKey, filesPage, 2, TimeUnit.HOURS);
|
||||
}
|
||||
}
|
||||
return filesPage;
|
||||
}
|
||||
|
||||
@ -229,6 +251,7 @@ public class FilesServiceImpl extends ServiceImpl<FilesMapper, Files> implements
|
||||
|
||||
return null; // 或返回空分页对象 new Page<>(0)
|
||||
}
|
||||
|
||||
private boolean isValidPage(IPage<Files> page) {
|
||||
return page.getRecords() != null
|
||||
&& !page.getRecords().isEmpty()
|
||||
@ -240,15 +263,14 @@ public class FilesServiceImpl extends ServiceImpl<FilesMapper, Files> implements
|
||||
* 用途说明:新增专项文档管理-文档内容
|
||||
* 参数说明
|
||||
* Files 文档内容
|
||||
* sourcePath 源路径
|
||||
* targetPath 目标路径
|
||||
* 返回值说明: com.yfd.platform.config.ResponseResult 返回新增成功或者失败
|
||||
***********************************/
|
||||
@Override
|
||||
public ResponseResult addFiles(Files files) {
|
||||
public ResponseResult addFiles(Files files) throws Exception {
|
||||
Boolean value = false;
|
||||
|
||||
List<String> names = Arrays.asList(files.getFileName().split(","));
|
||||
List<String> sizes = Arrays.asList(files.getFileSize().split(","));
|
||||
|
||||
//todo 新增成功以后 删除redis
|
||||
for (int page = 1; page <= 5; page++) {
|
||||
String redisKey = "sdfiles_" + files.getProjectId() + "_" + files.getNodeId() + "_page_" + page;
|
||||
@ -256,73 +278,56 @@ public class FilesServiceImpl extends ServiceImpl<FilesMapper, Files> implements
|
||||
}
|
||||
LOGGER.info("已清理缓存:project={}, node={}, pages=1-5", files.getProjectId(), files.getNodeId());
|
||||
|
||||
// 差不多的流程 就是提出来 然后判断 如果两个 中有一个是true
|
||||
//获取当前登录用户 上传人是当前登录人
|
||||
UsernamePasswordAuthenticationToken authentication =
|
||||
(UsernamePasswordAuthenticationToken) SecurityContextHolder.getContext().getAuthentication();
|
||||
LoginUser loginuser = (LoginUser) authentication.getPrincipal();
|
||||
|
||||
|
||||
// 数据校验
|
||||
if (names.size() != sizes.size()) {
|
||||
return ResponseResult.error("文件名称和文件大小的列表长度不一致!");
|
||||
}
|
||||
List<Files> filesToSave = new ArrayList<>();
|
||||
// 设置当前时间
|
||||
LocalDateTime now = LocalDateTime.now();
|
||||
// 转换为 Timestamp
|
||||
Timestamp currentTime = Timestamp.valueOf(now);
|
||||
files.setUploadTime(currentTime);
|
||||
|
||||
|
||||
for (int i = 0; i < names.size(); i++) {
|
||||
String name = names.get(i).trim();
|
||||
String sizeStr = sizes.get(i).trim();
|
||||
|
||||
// 校验文件名是否包含非法字符
|
||||
if (containsInvalidCharacters(name)) {
|
||||
return ResponseResult.error("文件名包含非法字符!");
|
||||
LoginUser loginuser = null;
|
||||
if (authentication != null) {
|
||||
loginuser = (LoginUser) authentication.getPrincipal();
|
||||
}
|
||||
|
||||
//新增之前从处理一下源路径的数据 ,String sourcePath,String targetPath
|
||||
// 查询本地文件路径根目录(如 E:\yun)
|
||||
QueryWrapper<StorageSourceConfig> queryWrapper = new QueryWrapper<>();
|
||||
queryWrapper.eq("name", "filePath");
|
||||
queryWrapper.eq("type", "sdlocal");
|
||||
StorageSourceConfig storageSourceConfig = storageSourceConfigMapper.selectOne(queryWrapper);
|
||||
//源路径 临时路径
|
||||
String sourceFilePath = files.getSourcePath();
|
||||
//目标路径
|
||||
String targetFilePath = files.getTargetPath();
|
||||
|
||||
List<Files> filesToSave = this.documentUploadById(files, sourceFilePath, targetFilePath, storageSourceConfig.getValue());
|
||||
|
||||
if (filesToSave.size() > 0) {
|
||||
//循环新增
|
||||
for (Files filess : filesToSave) {
|
||||
if (loginuser != null) {
|
||||
filess.setUploader(loginuser.getUsername());
|
||||
}
|
||||
//校验是否真正上传
|
||||
String pathAndName = files.getFilePath() + "/" + name;
|
||||
String pathAndName = filess.getFilePath() + filess.getFileName();
|
||||
//准备获取文件的信息
|
||||
AbstractBaseFileService<?> fileService = storageSourceContext.getByStorageKey("sdlocal");
|
||||
FileItemResult fileItemResult = fileService.getFileItem(pathAndName);
|
||||
if (fileItemResult == null || fileItemResult.getName() == null) {
|
||||
return ResponseResult.error(name + "文件没有上传到空间,请重新选择上传!");
|
||||
return ResponseResult.error(filess.getFileName() + "文件没有上传到空间,请重新选择上传!");
|
||||
}
|
||||
|
||||
// 校验文件大小是否可以转换成数值
|
||||
try {
|
||||
Files files1 = new Files();
|
||||
files1.setProjectId(files.getProjectId());
|
||||
files1.setNodeId(files.getNodeId());
|
||||
files1.setFilePath(files.getFilePath());
|
||||
files1.setKeywords(files.getKeywords());
|
||||
files1.setDescription(files.getDescription());
|
||||
files1.setUploadTime(files.getUploadTime());
|
||||
files1.setUploader(loginuser.getUsername());
|
||||
files1.setFileName(name);
|
||||
files1.setFileSize(sizeStr);
|
||||
filesToSave.add(files1);
|
||||
} catch (NumberFormatException e) {
|
||||
return ResponseResult.error("文件大小必须是有效的数字!");
|
||||
}
|
||||
}
|
||||
if (filesToSave.size() > 0) {
|
||||
//循环新增
|
||||
for (Files filess : filesToSave) {
|
||||
int valueAdded = filesMapper.insert(filess);
|
||||
if (valueAdded == 1) {
|
||||
|
||||
|
||||
value = true;
|
||||
} else {
|
||||
value = false;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
value = true;
|
||||
LOGGER.info("文件名相同覆盖 {}", files.getFileName());
|
||||
}
|
||||
File target = new File(storageSourceConfig.getValue() + String.valueOf(sourceFilePath));
|
||||
//删除临时文件
|
||||
deleteDirectory(target);
|
||||
|
||||
if (value) {
|
||||
return ResponseResult.success("新增文件成功!");
|
||||
} else {
|
||||
@ -330,6 +335,251 @@ public class FilesServiceImpl extends ServiceImpl<FilesMapper, Files> implements
|
||||
}
|
||||
}
|
||||
|
||||
public static void deleteDirectory(File directory) throws Exception {
|
||||
if (!directory.exists()) {
|
||||
return; // 路径不存在直接返回
|
||||
}
|
||||
|
||||
File[] files = directory.listFiles();
|
||||
if (files != null) {
|
||||
for (File file : files) {
|
||||
if (file.isDirectory()) {
|
||||
deleteDirectory(file); // 递归删除子目录
|
||||
} else {
|
||||
if (!file.delete()) { // 删除文件
|
||||
throw new Exception("无法删除文件: " + file.getAbsolutePath());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!directory.delete()) { // 删除空目录
|
||||
throw new Exception("无法删除目录: " + directory.getAbsolutePath());
|
||||
}
|
||||
}
|
||||
|
||||
public List<Files> documentUploadById(Files files, String sourceFilePath, String targetFilePath, String value) throws Exception {
|
||||
|
||||
List<Files> filesList = new ArrayList<>();
|
||||
|
||||
// 设置当前时间
|
||||
LocalDateTime now = LocalDateTime.now();
|
||||
// 转换为 Timestamp
|
||||
Timestamp currentTime = Timestamp.valueOf(now);
|
||||
FileListRequest sourcefileListRequest = buildFileRequest(sourceFilePath);
|
||||
FileListRequest targetfileListRequest = buildFileRequest(targetFilePath);
|
||||
|
||||
//获取源文件列表 包含文件和文件夹
|
||||
List<FileItemResult> sourceFileItemList = obtainFileItemResultData(sourcefileListRequest);
|
||||
//获取目标文件列表 包含文件和文件夹
|
||||
List<FileItemResult> targetFileItemList = obtainFileItemResultData(targetfileListRequest);
|
||||
for (FileItemResult fileItemResult : sourceFileItemList) {
|
||||
|
||||
String a1 = fileItemResult.getType() + fileItemResult.getName();
|
||||
FileItemResult targetFileItem = targetFileItemList.stream()
|
||||
.filter(t -> (t.getType() + t.getName()).equals(a1))
|
||||
.findFirst() // 获取第一个匹配项(返回 Optional)
|
||||
.orElse(null);
|
||||
|
||||
// 检查对象存在
|
||||
if (targetFileItem != null) {
|
||||
// 循环处理文件 对比文件的MD5值
|
||||
if (fileItemResult.getType() == FileTypeEnum.FILE) {
|
||||
//源路径
|
||||
String sourcePath = value + sourceFilePath + "/" + fileItemResult.getName();
|
||||
//目标路径
|
||||
String targetPath = value + targetFilePath + "/" + fileItemResult.getName();
|
||||
//根据路径获取MD5值比较 如果相同则不进行操作 如果不同则重命名目标路径下的文件名称以及表结构 把现在源路径下的文件拷贝到目标路径下 新增数据库文件记录
|
||||
// 计算源文件MD5
|
||||
File sourceLocalFile = new File(sourcePath);
|
||||
String sourceLocalMD5 = calculateMD5Data(new FileInputStream(sourceLocalFile));
|
||||
// 计算源文件MD5
|
||||
File targetLocalFile = new File(targetPath);
|
||||
String targetLocalMD5 = calculateMD5Data(new FileInputStream(targetLocalFile));
|
||||
|
||||
// 如果MD5值不相同则进行操作 //如果一致 则直接复制源文件到目标文件
|
||||
if (StringUtils.isNoneEmpty(sourceLocalMD5, targetLocalMD5) && !sourceLocalMD5.equals(targetLocalMD5)) {
|
||||
//更改目标路径下的文件名称
|
||||
String newTargetPath = renameFile(sourcePath);
|
||||
//将源目录文件 复制到 目标目录文件
|
||||
copyToDirectoryFile(newTargetPath, value + targetFilePath + "/");
|
||||
String normalizedPath = newTargetPath
|
||||
.replaceAll("[/\\\\]+", "/") // 将 "\" 或混合分隔符统一为 "/"
|
||||
.replaceAll("/+$", "");
|
||||
|
||||
String fileName = normalizedPath.substring(normalizedPath.lastIndexOf("/") + 1);
|
||||
Files files1 = new Files();
|
||||
files1.setProjectId(files.getProjectId());
|
||||
files1.setNodeId(files.getNodeId());
|
||||
files1.setFileName(fileName);
|
||||
//todo
|
||||
files1.setFilePath(targetFilePath);
|
||||
long fileSizeInBytes = fileItemResult.getSize();
|
||||
// 转换为 MB 并保留两位小数
|
||||
double fileSizeInMB = fileSizeInBytes / (1024.0 * 1024.0);
|
||||
String fileSizeFormatted = String.format("%.2f", fileSizeInMB); // 保留两位小数
|
||||
files1.setFileSize(fileSizeFormatted);
|
||||
files1.setUploadTime(currentTime);
|
||||
filesList.add(files1);
|
||||
} else {
|
||||
//将源目录文件 复制到 目标目录文件 todo这个地方是覆盖
|
||||
copyWithOverride(sourcePath, targetPath);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
//如果为空对象不存在 则直接拷贝
|
||||
String sourcePath = value + sourceFilePath;
|
||||
//目标路径
|
||||
String targetPath = value + targetFilePath;
|
||||
//将源目录文件 复制到 目标目录文件
|
||||
copyFolderWithOverride(sourcePath, targetPath);
|
||||
//这个时候要新增
|
||||
Files files1 = new Files();
|
||||
files1.setProjectId(files.getProjectId());
|
||||
files1.setNodeId(files.getNodeId());
|
||||
files1.setFileName(fileItemResult.getName());
|
||||
//todo
|
||||
files1.setFilePath(targetFilePath);
|
||||
long fileSizeInBytes = fileItemResult.getSize();
|
||||
// 转换为 MB 并保留两位小数
|
||||
double fileSizeInMB = fileSizeInBytes / (1024.0 * 1024.0);
|
||||
String fileSizeFormatted = String.format("%.2f", fileSizeInMB); // 保留两位小数
|
||||
files1.setFileSize(fileSizeFormatted);
|
||||
files1.setUploadTime(currentTime);
|
||||
filesList.add(files1);
|
||||
}
|
||||
}
|
||||
return filesList;
|
||||
}
|
||||
|
||||
/**
|
||||
* 确保路径格式为以 "/" 开头和结尾(例如 "/data/test/")
|
||||
* 若路径为空或非法,返回根路径 "/"
|
||||
*/
|
||||
private String ensurePathFormat(String path) {
|
||||
if (StringUtils.isBlank(path)) {
|
||||
return "/";
|
||||
}
|
||||
// 统一替换反斜杠为斜杠(兼容 Windows 路径)
|
||||
String normalized = path.replaceAll("\\\\", "/");
|
||||
// 去掉多余的斜杠
|
||||
normalized = normalized.replaceAll("/{2,}", "/");
|
||||
// 确保以 "/" 开头
|
||||
if (!normalized.startsWith("/")) {
|
||||
normalized = "/" + normalized;
|
||||
}
|
||||
// 确保以 "/" 结尾
|
||||
if (!normalized.endsWith("/")) {
|
||||
normalized += "/";
|
||||
}
|
||||
return normalized;
|
||||
}
|
||||
|
||||
// 优化后的 MD5 计算方法(线程安全)
|
||||
public String calculateMD5Data(InputStream inputStream) throws IOException, NoSuchAlgorithmException {
|
||||
try (InputStream is = inputStream) { // 确保流关闭
|
||||
MessageDigest md = MessageDigest.getInstance("MD5");
|
||||
byte[] buffer = new byte[8192];
|
||||
int bytesRead;
|
||||
while ((bytesRead = is.read(buffer)) != -1) {
|
||||
md.update(buffer, 0, bytesRead);
|
||||
}
|
||||
return Hex.encodeHexString(md.digest());
|
||||
}
|
||||
}
|
||||
|
||||
public static String renameFile(String originalPath) throws IOException {
|
||||
// JSONObject jsonObject = new JSONObject()
|
||||
File originalFile = new File(originalPath);
|
||||
if (!originalFile.exists()) {
|
||||
throw new IOException("原文件不存在: " + originalPath);
|
||||
}
|
||||
|
||||
// 生成新文件名(保留扩展名)
|
||||
String baseName = FilenameUtils.getBaseName(originalPath);
|
||||
String extension = FilenameUtils.getExtension(originalPath);
|
||||
String timestamp = LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyyMMddHHmmss"));
|
||||
String newFileName = baseName + "_" + timestamp + "." + extension;
|
||||
|
||||
Path originalFilePath = originalFile.toPath();
|
||||
Path newFilePath = Paths.get(originalFile.getParent(), newFileName);
|
||||
|
||||
// 处理目标文件已存在的情况
|
||||
if (java.nio.file.Files.exists(newFilePath)) {
|
||||
java.nio.file.Files.delete(newFilePath); // 删除已存在的目标文件
|
||||
}
|
||||
|
||||
// 移动文件
|
||||
java.nio.file.Files.move(originalFilePath, newFilePath);
|
||||
System.out.println("重命名成功: " + originalPath + " → " + newFilePath.toString());
|
||||
return newFilePath.toString();
|
||||
// jsonObject.set("paht",newFilePath.toString());
|
||||
// jsonObject.set("name",newFileName);
|
||||
}
|
||||
|
||||
private static void copyWithOverride(String source, String target) throws IOException {
|
||||
File srcFile = new File(source);
|
||||
File destFile = new File(target);
|
||||
|
||||
// 强制覆盖已存在的文件
|
||||
FileUtils.copyFile(srcFile, destFile, true);
|
||||
System.out.println("成功覆盖文件: " + target);
|
||||
}
|
||||
|
||||
private static void copyToDirectoryFile(String source, String targetDirectory) throws IOException {
|
||||
File srcFile = new File(source);
|
||||
File destDir = new File(targetDirectory);
|
||||
|
||||
// 确保目标目录存在,如果不存在则创建
|
||||
if (!destDir.exists()) {
|
||||
destDir.mkdirs();
|
||||
}
|
||||
|
||||
// 创建目标文件对象(在目标目录下使用源文件名)
|
||||
File destFile = new File(destDir, srcFile.getName());
|
||||
|
||||
// 复制文件到目标目录
|
||||
FileUtils.copyFile(srcFile, destFile);
|
||||
System.out.println("成功复制文件到: " + destFile.getAbsolutePath());
|
||||
}
|
||||
|
||||
private static void copyFolderWithOverride(String source, String target) throws IOException {
|
||||
File srcDir = new File(source);
|
||||
File destDir = new File(target);
|
||||
|
||||
|
||||
// 递归拷贝文件夹及内容
|
||||
FileUtils.copyDirectory(srcDir, destDir);
|
||||
System.out.println("成功覆盖文件夹: " + target);
|
||||
}
|
||||
|
||||
|
||||
private List<FileItemResult> obtainFileItemResultData(FileListRequest fileListRequest) throws Exception {
|
||||
|
||||
String storageKey = fileListRequest.getStorageKey();
|
||||
Integer storageId = storageSourceService.findIdByKey(storageKey);
|
||||
if (storageId == null) {
|
||||
throw new InvalidStorageSourceException("通过存储源 key 未找到存储源, key: " + storageKey);
|
||||
}
|
||||
// 处理请求参数默认值
|
||||
fileListRequest.handleDefaultValue();
|
||||
AbstractBaseFileService<?> fileService = storageSourceContext.getByStorageId(storageId);
|
||||
//todo 首先获取两个集合 对比出数据库中没有的文件夹以及文件,递归增加
|
||||
List<FileItemResult> fileItemList = fileService.fileList(fileListRequest.getPath());
|
||||
return fileItemList;
|
||||
}
|
||||
|
||||
private FileListRequest buildFileRequest(String path) {
|
||||
FileListRequest fileListRequest = new FileListRequest();
|
||||
fileListRequest.setOrderBy("time");
|
||||
fileListRequest.setOrderDirection("desc");
|
||||
fileListRequest.setPassword("");
|
||||
fileListRequest.setPath(path);
|
||||
fileListRequest.setStorageKey("sdlocal");
|
||||
|
||||
return fileListRequest;
|
||||
}
|
||||
|
||||
/**********************************
|
||||
* 用途说明: 修改专项文档管理-文档内容
|
||||
* 参数说明
|
||||
|
@ -19,6 +19,7 @@ import com.yfd.platform.modules.storage.service.base.AbstractBaseFileService;
|
||||
import com.yfd.platform.system.mapper.SysDictionaryItemsMapper;
|
||||
import com.yfd.platform.utils.StringUtils;
|
||||
import io.netty.channel.ChannelInboundHandlerAdapter;
|
||||
import net.bytebuddy.implementation.bytecode.Throw;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.stereotype.Service;
|
||||
@ -124,6 +125,15 @@ public class ProjectServiceImpl extends ServiceImpl<ProjectMapper, Project> impl
|
||||
// 转换为 Timestamp
|
||||
Timestamp currentTime = Timestamp.valueOf(now);
|
||||
project.setCreateTime(currentTime);
|
||||
|
||||
LambdaQueryWrapper<Project> queryWrapper = new LambdaQueryWrapper<>();
|
||||
queryWrapper.eq(Project::getProjectName,project.getProjectName());
|
||||
Project project1 = projectMapper.selectOne(queryWrapper);
|
||||
if (project1 != null){
|
||||
throw new RuntimeException("专项文档管理项目已存在!");
|
||||
}
|
||||
|
||||
|
||||
int valueAdded = projectMapper.insert(project);
|
||||
if (valueAdded == 1) {
|
||||
|
||||
@ -226,7 +236,6 @@ public class ProjectServiceImpl extends ServiceImpl<ProjectMapper, Project> impl
|
||||
if (project.getProjectTime() == null || project.getProjectTime().equals("")) {
|
||||
project.setProjectTime(null);
|
||||
}
|
||||
|
||||
int valueUpdate = projectMapper.updateById(project);
|
||||
if (valueUpdate == 1) {
|
||||
return true;
|
||||
|
Loading…
Reference in New Issue
Block a user