diff --git a/java/src/main/java/com/yfd/platform/modules/experimentalData/service/impl/TsFilesServiceImpl.java b/java/src/main/java/com/yfd/platform/modules/experimentalData/service/impl/TsFilesServiceImpl.java index fcefb6c..2beb79d 100644 --- a/java/src/main/java/com/yfd/platform/modules/experimentalData/service/impl/TsFilesServiceImpl.java +++ b/java/src/main/java/com/yfd/platform/modules/experimentalData/service/impl/TsFilesServiceImpl.java @@ -273,9 +273,6 @@ public class TsFilesServiceImpl extends ServiceImpl impl 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; diff --git a/java/src/main/java/com/yfd/platform/modules/specialDocument/controller/FilesController.java b/java/src/main/java/com/yfd/platform/modules/specialDocument/controller/FilesController.java index 48248df..6c2e94d 100644 --- a/java/src/main/java/com/yfd/platform/modules/specialDocument/controller/FilesController.java +++ b/java/src/main/java/com/yfd/platform/modules/specialDocument/controller/FilesController.java @@ -80,18 +80,12 @@ public class FilesController { @ApiOperation("新增专项文档管理文档内容") @ResponseBody @PreAuthorize("@el.check('add:files')") - public ResponseResult addFiles(@RequestBody Files files,String sourcePath,String targetPath) throws Exception { + public ResponseResult addFiles(@RequestBody Files files) throws Exception { //对象不能为空 if (ObjUtil.isEmpty(files)) { return ResponseResult.error("参数为空"); } - if (StrUtil.isEmpty(sourcePath)) { - return ResponseResult.error("源路径参数为空"); - } - if (StrUtil.isEmpty(targetPath)) { - return ResponseResult.error("目标路径参数为空"); - } - return filesService.addFiles(files,sourcePath,targetPath); + return filesService.addFiles(files); } diff --git a/java/src/main/java/com/yfd/platform/modules/specialDocument/domain/Files.java b/java/src/main/java/com/yfd/platform/modules/specialDocument/domain/Files.java index 492c6ec..1909e57 100644 --- a/java/src/main/java/com/yfd/platform/modules/specialDocument/domain/Files.java +++ b/java/src/main/java/com/yfd/platform/modules/specialDocument/domain/Files.java @@ -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; + } diff --git a/java/src/main/java/com/yfd/platform/modules/specialDocument/service/IFilesService.java b/java/src/main/java/com/yfd/platform/modules/specialDocument/service/IFilesService.java index a0c37ff..2bfec3d 100644 --- a/java/src/main/java/com/yfd/platform/modules/specialDocument/service/IFilesService.java +++ b/java/src/main/java/com/yfd/platform/modules/specialDocument/service/IFilesService.java @@ -43,7 +43,7 @@ public interface IFilesService extends IService { * targetPath 目标路径 * 返回值说明: com.yfd.platform.config.ResponseResult 返回新增成功或者失败 ***********************************/ - ResponseResult addFiles(Files files,String sourcePath,String targetPath) throws Exception; + ResponseResult addFiles(Files files) throws Exception; /********************************** * 用途说明: 修改专项文档管理-文档内容 diff --git a/java/src/main/java/com/yfd/platform/modules/specialDocument/service/impl/FilesServiceImpl.java b/java/src/main/java/com/yfd/platform/modules/specialDocument/service/impl/FilesServiceImpl.java index e245420..f5f22a6 100644 --- a/java/src/main/java/com/yfd/platform/modules/specialDocument/service/impl/FilesServiceImpl.java +++ b/java/src/main/java/com/yfd/platform/modules/specialDocument/service/impl/FilesServiceImpl.java @@ -3,6 +3,7 @@ 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.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; @@ -35,6 +36,7 @@ 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; @@ -47,6 +49,7 @@ 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; @@ -245,6 +248,7 @@ public class FilesServiceImpl extends ServiceImpl implements return null; // 或返回空分页对象 new Page<>(0) } + private boolean isValidPage(IPage page) { return page.getRecords() != null && !page.getRecords().isEmpty() @@ -261,31 +265,9 @@ public class FilesServiceImpl extends ServiceImpl implements * 返回值说明: com.yfd.platform.config.ResponseResult 返回新增成功或者失败 ***********************************/ @Override - public ResponseResult addFiles(Files files,String sourcePath,String targetPath) throws Exception { + public ResponseResult addFiles(Files files) throws Exception { Boolean value = false; - //新增之前从处理一下源路径的数据 - // 查询本地文件路径根目录(如 E:\yun) - QueryWrapper queryWrapper = new QueryWrapper<>(); - queryWrapper.eq("name", "filePath"); - queryWrapper.eq("type", "sdlocal"); - StorageSourceConfig storageSourceConfig = storageSourceConfigMapper.selectOne(queryWrapper); - //源路径 临时路径 - String sourceFilePath = storageSourceConfig.getValue()+sourcePath; - //目标路径 - String targetFilePath = storageSourceConfig.getValue()+targetPath; - - this.documentUploadById(files,sourceFilePath,targetFilePath,storageSourceConfig.getValue()); - - - - - - - - List names = Arrays.asList(files.getFileName().split(",")); - List sizes = Arrays.asList(files.getFileSize().split(",")); - //todo 新增成功以后 删除redis for (int page = 1; page <= 5; page++) { String redisKey = "sdfiles_" + files.getProjectId() + "_" + files.getNodeId() + "_page_" + page; @@ -293,73 +275,53 @@ public class FilesServiceImpl extends ServiceImpl 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("文件名称和文件大小的列表长度不一致!"); + LoginUser loginuser = null; + if (authentication != null) { + loginuser = (LoginUser) authentication.getPrincipal(); } - List filesToSave = new ArrayList<>(); - // 设置当前时间 - LocalDateTime now = LocalDateTime.now(); - // 转换为 Timestamp - Timestamp currentTime = Timestamp.valueOf(now); - files.setUploadTime(currentTime); + //新增之前从处理一下源路径的数据 ,String sourcePath,String targetPath + // 查询本地文件路径根目录(如 E:\yun) + QueryWrapper queryWrapper = new QueryWrapper<>(); + queryWrapper.eq("name", "filePath"); + queryWrapper.eq("type", "sdlocal"); + StorageSourceConfig storageSourceConfig = storageSourceConfigMapper.selectOne(queryWrapper); + //源路径 临时路径 + String sourceFilePath = files.getSourcePath(); + //目标路径 + String targetFilePath = files.getTargetPath(); - for (int i = 0; i < names.size(); i++) { - String name = names.get(i).trim(); - String sizeStr = sizes.get(i).trim(); + List filesToSave = this.documentUploadById(files, sourceFilePath, targetFilePath, storageSourceConfig.getValue()); - // 校验文件名是否包含非法字符 - if (containsInvalidCharacters(name)) { - return ResponseResult.error("文件名包含非法字符!"); - } - - //校验是否真正上传 - String pathAndName = files.getFilePath() + "/" + name; - //准备获取文件的信息 - AbstractBaseFileService fileService = storageSourceContext.getByStorageKey("sdlocal"); - FileItemResult fileItemResult = fileService.getFileItem(pathAndName); - if (fileItemResult == null || fileItemResult.getName() == null) { - return ResponseResult.error(name + "文件没有上传到空间,请重新选择上传!"); - } - - // 校验文件大小是否可以转换成数值 - 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) { + if (loginuser != null) { + filess.setUploader(loginuser.getUsername()); + } + //校验是否真正上传 + 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(filess.getFileName() + "文件没有上传到空间,请重新选择上传!"); + } int valueAdded = filesMapper.insert(filess); if (valueAdded == 1) { - - value = true; } else { value = false; } } } + File target = new File(storageSourceConfig.getValue() + String.valueOf(sourceFilePath)); + //删除临时文件 + deleteDirectory(target); + if (value) { return ResponseResult.success("新增文件成功!"); } else { @@ -367,89 +329,145 @@ public class FilesServiceImpl extends ServiceImpl implements } } - public String documentUploadById(Files files, String sourceFilePath, String targetFilePath, String value) throws Exception { - return null; + 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 documentUploadById(Files files, String sourceFilePath, String targetFilePath, String value) throws Exception { + + List filesList = new ArrayList<>(); + + // 设置当前时间 + LocalDateTime now = LocalDateTime.now(); + // 转换为 Timestamp + Timestamp currentTime = Timestamp.valueOf(now); + FileListRequest sourcefileListRequest = buildFileRequest(sourceFilePath); + FileListRequest targetfileListRequest = buildFileRequest(targetFilePath); + + //获取源文件列表 包含文件和文件夹 + List sourceFileItemList = obtainFileItemResultData(sourcefileListRequest); + //获取目标文件列表 包含文件和文件夹 + List 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; } -// List filesList = new ArrayList<>(); -// -// -// //源目录 -// File sourceDir = new File(sourceFilePath); -// //目标目录 -// File targetDir = new File(targetFilePath); -// -// if (!targetDir.exists()) { -// FileUtils.copyDirectory(sourceDir, targetDir); -// LOGGER.info("目标文件没有,全部更新过去"); -// return null; -// } -// -// FileListRequest sourcefileListRequest = buildFileRequest(sourceFilePath); -// FileListRequest targetfileListRequest = buildFileRequest(targetFilePath); -// -// //获取源文件列表 包含文件和文件夹 -// List sourceFileItemList = obtainFileItemResultData(sourcefileListRequest); -// //获取目标文件列表 包含文件和文件夹 -// List 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 = sourceFilePath + "/" + fileItemResult.getName(); -// -// //目标路径 -// String targetPath = 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)) { -// LOGGER.info("MD5值不一样的路径" + sourcePath); -// LOGGER.info("MD5值不一样的替换路径" + targetPath); -// //拷贝文件到目标目录 将原来的文件名更改以及将数据库表结构更改 -// //更改目标路径下的文件名称 -// String newTargetPath = renameFile(sourcePath); -// //将源目录文件 复制到 目标目录文件 -// copyToDirectoryFile(newTargetPath, value + targetFolderPath + "/"); -// -// } else { -// //将源目录文件 复制到 目标目录文件 todo这个地方是覆盖 -// copyWithOverride(sourcePath, targetPath); -// } -// } -// } else { -// //如果为空对象不存在 则直接拷贝 -// String sourcePath = value + sourceFilePath; -// //目标路径 就是源路径去掉/temporary的部分 -// String targetPath = sourcePath.replace("/" + "temporary", ""); -// //将源目录文件 复制到 目标目录文件 -// copyFolderWithOverride(sourcePath, targetPath); -// -// } -// } -// -// -// -// -// -// return null; -// } // 优化后的 MD5 计算方法(线程安全) public String calculateMD5Data(InputStream inputStream) throws IOException, NoSuchAlgorithmException { @@ -465,6 +483,7 @@ public class FilesServiceImpl extends ServiceImpl implements } public static String renameFile(String originalPath) throws IOException { + // JSONObject jsonObject = new JSONObject() File originalFile = new File(originalPath); if (!originalFile.exists()) { throw new IOException("原文件不存在: " + originalPath); @@ -488,6 +507,8 @@ public class FilesServiceImpl extends ServiceImpl implements 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 { @@ -553,12 +574,12 @@ public class FilesServiceImpl extends ServiceImpl implements return fileListRequest; } - /********************************** - * 用途说明: 修改专项文档管理-文档内容 - * 参数说明 - * Files 文档内容 - * 返回值说明: com.yfd.platform.config.ResponseResult 返回修改成功或者失败 - ***********************************/ + /********************************** + * 用途说明: 修改专项文档管理-文档内容 + * 参数说明 + * Files 文档内容 + * 返回值说明: com.yfd.platform.config.ResponseResult 返回修改成功或者失败 + ***********************************/ @Override @Transactional(rollbackFor = Exception.class)// 添加事务注解,遇到异常时回滚 public boolean updateFiles(Files files) {