From 338fbee1ff4438789bd9ec8eb7e50b1b6988a8ff Mon Sep 17 00:00:00 2001 From: lilin Date: Tue, 10 Jun 2025 10:38:20 +0800 Subject: [PATCH] =?UTF-8?q?=E4=BC=98=E5=8C=96=E4=B8=93=E9=A1=B9=E6=96=87?= =?UTF-8?q?=E6=A1=A3=E4=B8=8A=E4=BC=A0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../service/impl/NodesServiceImpl.java | 186 +++++++++++++----- 1 file changed, 140 insertions(+), 46 deletions(-) diff --git a/java/src/main/java/com/yfd/platform/modules/specialDocument/service/impl/NodesServiceImpl.java b/java/src/main/java/com/yfd/platform/modules/specialDocument/service/impl/NodesServiceImpl.java index 729ed8c..e989d1d 100644 --- a/java/src/main/java/com/yfd/platform/modules/specialDocument/service/impl/NodesServiceImpl.java +++ b/java/src/main/java/com/yfd/platform/modules/specialDocument/service/impl/NodesServiceImpl.java @@ -1110,71 +1110,165 @@ public class NodesServiceImpl extends ServiceImpl implements @Override @Async("asyncExecutor") public void documentUploadByIdAsync(String id, String fileName, LoginUser loginuser) throws IOException { + // 生成唯一Key(提前到方法开头,确保异常时也能标记完成) + final String asyncKey = taskStatusHolder.documentUploadKey(id); + Path destRootPath = null; + File targetZip = null; + File targetDir = null; + try { + // 1. 优化:合并重复的异常捕获 + //------------------------------------------ + // 查询存储配置 + StorageSourceConfig config = getStorageConfig(); + if (config == null) throw new RuntimeException("未找到本地存储路径配置"); - // 查询本地文件路径根目录(如 E:\yun) - QueryWrapper queryWrapper = new QueryWrapper<>(); - queryWrapper.eq("name", "filePath"); - queryWrapper.eq("type", "sdlocal"); - StorageSourceConfig storageSourceConfig = storageSourceConfigMapper.selectOne(queryWrapper); - - //解压以后的文件夹名称 - String zipName = getFileNameWithoutExtension(fileName); // 示例:222 - - //查询项目信息 + // 优化:提前验证项目存在性(避免后续无效操作) Project project = projectMapper.selectById(id); + if (project == null) throw new RuntimeException("项目不存在: " + id); + // 优化:解压路径统一构建逻辑 + final String tempDir = "temporary"; + final String zipName = getFileNameWithoutExtension(fileName); + + // 验证压缩包名称匹配 if (!project.getProjectName().equals(zipName)) { - throw new RuntimeException("压缩包名称需要和项目名称保持一致"); + throw new RuntimeException("压缩包名称[" + zipName + "]需与项目名称[" + project.getProjectName() + "]保持一致"); } - String decompressionPath = "/" + "temporary"; - //构建要解压的zip文件路径 例如 D:\yun\temporary\111.zip - Path zipFilePath = Paths.get(storageSourceConfig.getValue(), decompressionPath, fileName); - // 4. 构建解压目标路径 例如 D:\yun\temporary\111 - Path destRoot = Paths.get(storageSourceConfig.getValue(), decompressionPath); + // 2. 优化:路径构建使用统一变量 + //------------------------------------------ + Path zipFilePath = Paths.get(config.getValue(), tempDir, fileName); + Path destRoot = Paths.get(config.getValue(), tempDir); + destRootPath = Paths.get(config.getValue(), tempDir, zipName); // 记录后续清理路径 + targetZip = zipFilePath.toFile(); + targetDir = destRootPath.toFile(); - LOGGER.info("要解压文件路径:{}", zipFilePath); - LOGGER.info("解压以后文件路径:{}", destRoot); + LOGGER.info("解压源文件: {} => 目标目录: {}", zipFilePath, destRoot); - - //todo 如果项目不存在 直接拷贝到目标路径下 拷贝完成以后 然后新增一个项目结构 然后走一遍扫描 - - //源文件夹路径 - String sourceFolderPath = "/" + "temporary" + "/" + zipName + "/"; - //目标文件夹路径 - String targetFolderPath = "/" + project.getProjectName() + "/"; - - //首先执行解压缩 - unzipToTemp(zipFilePath, String.valueOf(destRoot)); - // 执行上传并且插入数据库 - this.documentUploadById(id, sourceFolderPath, targetFolderPath, storageSourceConfig.getValue()); - //开始执行更新表数据 名称是去掉后缀以后的 + // 3. 优化:解压和文件操作分离 + //------------------------------------------ + unzipToTemp(zipFilePath, destRoot.toString()); + transferProjectFiles(id, config.getValue(), zipName, project.getProjectName()); uploadProject(zipName, loginuser); - LOGGER.info("开始更新表数据:{}", zipName); + LOGGER.info("项目数据更新完成: {}", zipName); - //获取文件路径 - Path destRootPath = Paths.get(storageSourceConfig.getValue(), decompressionPath, zipName); - File targetZip = new File(String.valueOf(zipFilePath)); - File target = new File(String.valueOf(destRootPath)); - //删除临时文件ZIP - deleteDirectory(targetZip); - //删除临时文件 - deleteDirectory(target); - } catch (IOException e) { - throw new RuntimeException(e); } catch (Exception e) { + // 优化:统一异常处理(原有两个catch合并) + LOGGER.error("文档上传失败: {}", e.getMessage(), e); throw new RuntimeException(e); } finally { - // 生成唯一Key - String asyncKey = taskStatusHolder.documentUploadKey(id); - // 无论成功失败都标记完成 + // 4. 关键优化:确保资源清理(无论成功失败都执行) + //------------------------------------------ + cleanupTempResources(targetZip, targetDir); + + // 标记任务完成(确保任何情况下都会执行) taskStatusHolder.finishTask(asyncKey); WebSocketServer.sendMessageTo("专项文档上传任务处理完成!", "projectId_" + id); - } } + // 新增辅助方法:解耦核心逻辑 -------------------------------------------------- + private StorageSourceConfig getStorageConfig() { + QueryWrapper wrapper = new QueryWrapper<>(); + wrapper.eq("name", "filePath").eq("type", "sdlocal"); + return storageSourceConfigMapper.selectOne(wrapper); + } + + private void transferProjectFiles(String projectId, String basePath, String sourceDir, String targetDir) throws Exception { + String sourcePath = "/temporary/" + sourceDir + "/"; + String targetPath = "/" + targetDir + "/"; + documentUploadById(projectId, sourcePath, targetPath, basePath); + } + + // 关键优化:独立的资源清理方法(确保异常时仍能执行清理) + private void cleanupTempResources(File zipFile, File tempDir) { + try { + if (zipFile != null && zipFile.exists()) { + deleteDirectory(zipFile); // 删除临时ZIP + LOGGER.debug("清理临时ZIP: {}", zipFile.getAbsolutePath()); + } + if (tempDir != null && tempDir.exists()) { + deleteDirectory(tempDir); // 删除解压目录 + LOGGER.debug("清理临时目录: {}", tempDir.getAbsolutePath()); + } + } catch (Exception e) { + LOGGER.warn("临时资源清理失败", e); // 不阻断主流程 + } + } + +// public void documentUploadByIdAsync(String id, String fileName, LoginUser loginuser) throws IOException { +// try { +// +// // 查询本地文件路径根目录(如 E:\yun) +// QueryWrapper queryWrapper = new QueryWrapper<>(); +// queryWrapper.eq("name", "filePath"); +// queryWrapper.eq("type", "sdlocal"); +// StorageSourceConfig storageSourceConfig = storageSourceConfigMapper.selectOne(queryWrapper); +// +// if (storageSourceConfig == null) { +// throw new RuntimeException("未找到本地存储路径配置"); +// } +// +// //解压以后的文件夹名称 +// String zipName = getFileNameWithoutExtension(fileName); // 示例:222 +// +// //查询项目信息 +// Project project = projectMapper.selectById(id); +// if (project == null) { +// throw new RuntimeException("项目不存在"); +// } +// +// if (!project.getProjectName().equals(zipName)) { +// throw new RuntimeException("压缩包名称需要和项目名称保持一致"); +// } +// +// String decompressionPath = "/" + "temporary"; +// //构建要解压的zip文件路径 例如 D:\yun\temporary\111.zip +// Path zipFilePath = Paths.get(storageSourceConfig.getValue(), decompressionPath, fileName); +// // 4. 构建解压目标路径 例如 D:\yun\temporary\111 +// Path destRoot = Paths.get(storageSourceConfig.getValue(), decompressionPath); +// +// LOGGER.info("要解压文件路径:{}", zipFilePath); +// LOGGER.info("解压以后文件路径:{}", destRoot); +// +// +// //todo 如果项目不存在 直接拷贝到目标路径下 拷贝完成以后 然后新增一个项目结构 然后走一遍扫描 +// +// //源文件夹路径 +// String sourceFolderPath = "/" + "temporary" + "/" + zipName + "/"; +// //目标文件夹路径 +// String targetFolderPath = "/" + project.getProjectName() + "/"; +// +// //首先执行解压缩 +// unzipToTemp(zipFilePath, String.valueOf(destRoot)); +// // 执行上传并且插入数据库 +// this.documentUploadById(id, sourceFolderPath, targetFolderPath, storageSourceConfig.getValue()); +// //开始执行更新表数据 名称是去掉后缀以后的 +// uploadProject(zipName, loginuser); +// LOGGER.info("开始更新表数据:{}", zipName); +// +// //获取文件路径 +// Path destRootPath = Paths.get(storageSourceConfig.getValue(), decompressionPath, zipName); +// File targetZip = new File(String.valueOf(zipFilePath)); +// File target = new File(String.valueOf(destRootPath)); +// //删除临时文件ZIP +// deleteDirectory(targetZip); +// //删除临时文件 +// deleteDirectory(target); +// } catch (IOException e) { +// throw new RuntimeException(e); +// } catch (Exception e) { +// throw new RuntimeException(e); +// } finally { +// // 生成唯一Key +// String asyncKey = taskStatusHolder.documentUploadKey(id); +// // 无论成功失败都标记完成 +// taskStatusHolder.finishTask(asyncKey); +// WebSocketServer.sendMessageTo("专项文档上传任务处理完成!", "projectId_" + id); +// +// } +// } public static void deleteDirectory(File directory) throws Exception { if (!directory.exists()) {