From 6cbbe721e89fe35ebc02645cbe21dcedfbf9962b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=B0=8F=E5=90=BE=E7=AB=8B?= Date: Wed, 24 Jul 2024 14:58:59 +0800 Subject: [PATCH] =?UTF-8?q?=F0=9F=90=9E=20fix(server):=20=E5=88=86?= =?UTF-8?q?=E5=8F=91=E6=96=87=E4=BB=B6=E4=BD=BF=E7=94=A8=E6=96=87=E4=BB=B6?= =?UTF-8?q?=E4=B8=AD=E5=BF=83=E6=88=96=E8=80=85=E9=9D=99=E6=80=81=E6=96=87?= =?UTF-8?q?=E4=BB=B6=E4=B8=8A=E4=BC=A0=E8=87=B3=E8=8A=82=E7=82=B9=E4=BD=BF?= =?UTF-8?q?=E7=94=A8=E5=AE=9E=E9=99=85=E6=96=87=E4=BB=B6=E5=90=8D?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- CHANGELOG-BETA.md | 1 + .../java/org/dromara/jpom/util/FileUtils.java | 12 ++++++++++++ .../org/dromara/jpom/build/ReleaseManage.java | 4 ++-- .../outgiving/OutGivingProjectController.java | 12 ++++++++---- .../controller/BaseDownloadApiController.java | 11 ----------- .../controller/FileStorageApiController.java | 3 ++- .../StaticFileStorageApiController.java | 3 ++- .../jpom/outgiving/OutGivingItemRun.java | 5 ++++- .../dromara/jpom/outgiving/OutGivingRun.java | 17 ++++++++++++----- web-vue/src/i18n/locales/en_us.json | 1 + web-vue/src/i18n/locales/zh_cn.json | 1 + web-vue/src/i18n/locales/zh_hk.json | 1 + web-vue/src/i18n/locales/zh_tw.json | 1 + .../src/pages/file-manager/fileStorage/list.vue | 2 ++ 14 files changed, 49 insertions(+), 25 deletions(-) diff --git a/CHANGELOG-BETA.md b/CHANGELOG-BETA.md index e95b1a858..593e1ac64 100644 --- a/CHANGELOG-BETA.md +++ b/CHANGELOG-BETA.md @@ -9,6 +9,7 @@ 3. 【all】优化 解析 HTTP `Accept-Language` 请求头支持多语言最高优先级 4. 【server】修复 页面未刷新情况下打开弹窗次数过多不能提示窗口层级太低(感谢[@lin_yeqi](https://gitee.com/lin_yeqi) [Gitee issues IAEBUZ](https://gitee.com/dromara/Jpom/issues/IAEBUZ) ) 5. 【server】优化 分发日志现在关联数据信息(感谢[@pumpkinor](https://gitee.com/pumpkinor) [Gitee issues IAF7IV](https://gitee.com/dromara/Jpom/issues/IAF7IV) ) +6. 【server】优化 分发文件使用文件中心或者静态文件上传至节点使用实际文件名(感谢[@pumpkinor](https://gitee.com/pumpkinor) [Gitee issues IAF7GD](https://gitee.com/dromara/Jpom/issues/IAF7GD) ) ------ diff --git a/modules/common/src/main/java/org/dromara/jpom/util/FileUtils.java b/modules/common/src/main/java/org/dromara/jpom/util/FileUtils.java index e69c3eb5c..37648ec38 100644 --- a/modules/common/src/main/java/org/dromara/jpom/util/FileUtils.java +++ b/modules/common/src/main/java/org/dromara/jpom/util/FileUtils.java @@ -17,6 +17,7 @@ import cn.hutool.core.io.NioUtil; import cn.hutool.core.map.MapUtil; import cn.hutool.core.util.CharsetUtil; import cn.hutool.core.util.IdUtil; +import cn.hutool.core.util.ReUtil; import cn.hutool.core.util.StrUtil; import com.alibaba.fastjson2.JSONObject; import lombok.Lombok; @@ -232,4 +233,15 @@ public class FileUtils { FileUtil.del(src); } } + + public static String safeFileName(String name1, String extName, String defaultName){ + // 需要考虑文件名中存在非法字符 [\s\\/:\*\?\"<>\|] + String name = ReUtil.replaceAll(name1, "[\\s\\\\/:\\*\\?\\\"<>\\|]", ""); + if (StrUtil.isEmpty(name)) { + name = defaultName; + } else if (!StrUtil.endWith(name, StrUtil.DOT + extName)) { + name += StrUtil.DOT + extName; + } + return name; + } } diff --git a/modules/server/src/main/java/org/dromara/jpom/build/ReleaseManage.java b/modules/server/src/main/java/org/dromara/jpom/build/ReleaseManage.java index 24ff1f2d8..efe54d5a8 100644 --- a/modules/server/src/main/java/org/dromara/jpom/build/ReleaseManage.java +++ b/modules/server/src/main/java/org/dromara/jpom/build/ReleaseManage.java @@ -556,7 +556,7 @@ public class ReleaseManage { // Set progressRangeList = ConcurrentHashMap.newKeySet((int) Math.floor((float) 100 / buildExtConfig.getLogReduceProgressRatio())); int finalI = i; - JsonMessage jsonMessage = OutGivingRun.fileUpload(file, startPath, + JsonMessage jsonMessage = OutGivingRun.fileUpload(file, file.getName(), startPath, projectId, false, last ? afterOpt : AfterOpt.No, nodeModel, false, this.buildExtraModule.getProjectUploadCloseFirst(), (total, progressSize) -> { double progressPercentage = Math.floor(((float) progressSize / total) * 100); @@ -604,7 +604,7 @@ public class ReleaseManage { JsonMessage jsonMessage = BuildUtil.loadDirPackage(this.buildExtraModule.getId(), this.getRealBuildNumberId(), this.resultFile, tarGz, (unZip, zipFile) -> { String name = zipFile.getName(); Set progressRangeList = ConcurrentHashMap.newKeySet((int) Math.floor((float) 100 / buildExtConfig.getLogReduceProgressRatio())); - return OutGivingRun.fileUpload(zipFile, + return OutGivingRun.fileUpload(zipFile, zipFile.getName(), this.buildExtraModule.getProjectSecondaryDirectory(), projectId, unZip, diff --git a/modules/server/src/main/java/org/dromara/jpom/controller/outgiving/OutGivingProjectController.java b/modules/server/src/main/java/org/dromara/jpom/controller/outgiving/OutGivingProjectController.java index af72a5b30..15c84cfe7 100644 --- a/modules/server/src/main/java/org/dromara/jpom/controller/outgiving/OutGivingProjectController.java +++ b/modules/server/src/main/java/org/dromara/jpom/controller/outgiving/OutGivingProjectController.java @@ -55,6 +55,7 @@ import org.dromara.jpom.service.node.ProjectInfoCacheService; import org.dromara.jpom.service.outgiving.DbOutGivingLogService; import org.dromara.jpom.service.outgiving.OutGivingServer; import org.dromara.jpom.system.ServerConfig; +import org.dromara.jpom.util.FileUtils; import org.dromara.jpom.util.StringUtil; import org.springframework.http.MediaType; import org.springframework.util.Assert; @@ -302,7 +303,7 @@ public class OutGivingProjectController extends BaseServerController { File file = FileUtil.file(serverConfig.getUserTempPath(), ServerConst.OUTGIVING_FILE, id); FileUtil.mkdir(file); File downloadFile = HttpUtil.downloadFileFromUrl(url, file); - this.startTask(outGivingModel, downloadFile, autoUnzip, stripComponents, selectProject, true); + this.startTask(outGivingModel, downloadFile, null, autoUnzip, stripComponents, selectProject, true); return JsonMessage.success(I18nMessageUtil.get("i18n.download_success_and_distribute.ae94")); } @@ -392,7 +393,8 @@ public class OutGivingProjectController extends BaseServerController { outGivingServer.updateById(outGivingModel); File storageSavePath = serverConfig.fileStorageSavePath(); File file = FileUtil.file(storageSavePath, storageModel.getPath()); - this.startTask(outGivingModel, file, autoUnzip, stripComponents, selectProject, false); + String fileName = FileUtils.safeFileName(storageModel.getName(), storageModel.getExtName(), "file-storage." + storageModel.getExtName()); + this.startTask(outGivingModel, file, fileName, autoUnzip, stripComponents, selectProject, false); return JsonMessage.success(I18nMessageUtil.get("i18n.start_distribution_exclamation.9fc2")); } @@ -426,7 +428,8 @@ public class OutGivingProjectController extends BaseServerController { outGivingServer.updateById(outGivingModel); File file = FileUtil.file(storageModel.getAbsolutePath()); - this.startTask(outGivingModel, file, autoUnzip, stripComponents, selectProject, false); + String fileName = FileUtils.safeFileName(storageModel.getName(), storageModel.getExtName(), "file-storage." + storageModel.getExtName()); + this.startTask(outGivingModel, file, fileName, autoUnzip, stripComponents, selectProject, false); return JsonMessage.success(I18nMessageUtil.get("i18n.start_distribution_exclamation.9fc2")); } @@ -439,7 +442,7 @@ public class OutGivingProjectController extends BaseServerController { * @param stripComponents 剔除目录 * @param selectProject 选择指定项目 */ - private void startTask(OutGivingModel outGivingModel, File file, String autoUnzip, + private void startTask(OutGivingModel outGivingModel, File file, String fileName, String autoUnzip, String stripComponents, String selectProject, boolean deleteFile) { @@ -454,6 +457,7 @@ public class OutGivingProjectController extends BaseServerController { .id(outGivingModel.getId()) .file(file) .userModel(getUser()) + .fileName(fileName) .unzip(unzip) .mode(outGivingModel.getMode()) .modeData(outGivingModel.getModeData()) diff --git a/modules/server/src/main/java/org/dromara/jpom/func/openapi/controller/BaseDownloadApiController.java b/modules/server/src/main/java/org/dromara/jpom/func/openapi/controller/BaseDownloadApiController.java index 58f3b17aa..68be11fca 100644 --- a/modules/server/src/main/java/org/dromara/jpom/func/openapi/controller/BaseDownloadApiController.java +++ b/modules/server/src/main/java/org/dromara/jpom/func/openapi/controller/BaseDownloadApiController.java @@ -86,17 +86,6 @@ public abstract class BaseDownloadApiController extends BaseJpomController { return new long[]{fromPos, downloadSize}; } - protected String convertName(String name1, String extName, String defaultName) { - // 需要考虑文件名中存在非法字符 - String name = ReUtil.replaceAll(name1, "[\\s\\\\/:\\*\\?\\\"<>\\|]", ""); - if (StrUtil.isEmpty(name)) { - name = defaultName; - } else if (!StrUtil.endWith(name, StrUtil.DOT + extName)) { - name += StrUtil.DOT + extName; - } - return name; - } - public void download(File file, long fileSize, String name, long[] resolveRange, HttpServletResponse response) throws IOException { Assert.state(FileUtil.isFile(file), I18nMessageUtil.get("i18n.file_does_not_exist_anymore.2fab")); String contentType = ObjectUtil.defaultIfNull(FileUtil.getMimeType(name), "application/octet-stream"); diff --git a/modules/server/src/main/java/org/dromara/jpom/func/openapi/controller/FileStorageApiController.java b/modules/server/src/main/java/org/dromara/jpom/func/openapi/controller/FileStorageApiController.java index aa3651ba2..c1f2bbdb7 100644 --- a/modules/server/src/main/java/org/dromara/jpom/func/openapi/controller/FileStorageApiController.java +++ b/modules/server/src/main/java/org/dromara/jpom/func/openapi/controller/FileStorageApiController.java @@ -27,6 +27,7 @@ import org.dromara.jpom.func.files.service.FileStorageService; import org.dromara.jpom.model.user.UserModel; import org.dromara.jpom.service.user.TriggerTokenLogServer; import org.dromara.jpom.system.ServerConfig; +import org.dromara.jpom.util.FileUtils; import org.springframework.http.MediaType; import org.springframework.util.Assert; import org.springframework.web.bind.annotation.GetMapping; @@ -131,7 +132,7 @@ public class FileStorageApiController extends BaseDownloadApiController { File storageSavePath = serverConfig.fileStorageSavePath(); File fileStorageFile = FileUtil.file(storageSavePath, storageModel.getPath()); // 需要考虑文件名中存在非法字符 - String name = this.convertName(storageModel.getName(), storageModel.getExtName(), fileStorageFile.getName()); + String name = FileUtils.safeFileName(storageModel.getName(), storageModel.getExtName(), fileStorageFile.getName()); // 解析断点续传相关信息 long fileSize = FileUtil.size(fileStorageFile); long[] resolveRange = this.resolveRange(request, fileSize, storageModel.getId(), storageModel.getName(), response); diff --git a/modules/server/src/main/java/org/dromara/jpom/func/openapi/controller/StaticFileStorageApiController.java b/modules/server/src/main/java/org/dromara/jpom/func/openapi/controller/StaticFileStorageApiController.java index bec42f55f..262aaf02d 100644 --- a/modules/server/src/main/java/org/dromara/jpom/func/openapi/controller/StaticFileStorageApiController.java +++ b/modules/server/src/main/java/org/dromara/jpom/func/openapi/controller/StaticFileStorageApiController.java @@ -19,6 +19,7 @@ import org.dromara.jpom.func.files.model.StaticFileStorageModel; import org.dromara.jpom.func.files.service.StaticFileStorageService; import org.dromara.jpom.model.user.UserModel; import org.dromara.jpom.service.user.TriggerTokenLogServer; +import org.dromara.jpom.util.FileUtils; import org.springframework.http.MediaType; import org.springframework.util.Assert; import org.springframework.web.bind.annotation.GetMapping; @@ -64,7 +65,7 @@ public class StaticFileStorageApiController extends BaseDownloadApiController { Assert.notNull(userModel, I18nMessageUtil.get("i18n.token_invalid_or_expired.cb96")); File file = FileUtil.file(storageModel.getAbsolutePath()); // 需要考虑文件名中存在非法字符 - String name = this.convertName(storageModel.getName(), storageModel.getExtName(), file.getName()); + String name = FileUtils.safeFileName(storageModel.getName(), storageModel.getExtName(), file.getName()); // 解析断点续传相关信息 long fileSize = FileUtil.size(file); long[] resolveRange = this.resolveRange(request, fileSize, storageModel.getId(), storageModel.getName(), response); diff --git a/modules/server/src/main/java/org/dromara/jpom/outgiving/OutGivingItemRun.java b/modules/server/src/main/java/org/dromara/jpom/outgiving/OutGivingItemRun.java index fb75eaf29..300ecb309 100644 --- a/modules/server/src/main/java/org/dromara/jpom/outgiving/OutGivingItemRun.java +++ b/modules/server/src/main/java/org/dromara/jpom/outgiving/OutGivingItemRun.java @@ -14,6 +14,7 @@ import cn.hutool.core.date.SystemClock; import cn.hutool.core.io.FileUtil; import cn.hutool.core.util.EnumUtil; import cn.hutool.core.util.ObjectUtil; +import cn.hutool.core.util.StrUtil; import cn.hutool.extra.spring.SpringUtil; import cn.keepbx.jpom.model.JsonMessage; import com.alibaba.fastjson2.JSONObject; @@ -50,6 +51,7 @@ public class OutGivingItemRun implements Callable { private final String secondaryDirectory; private final Boolean closeFirst; private int stripComponents; + private String fileName; public OutGivingItemRun(OutGivingModel item, OutGivingNodeProject outGivingNodeProject, @@ -76,6 +78,7 @@ public class OutGivingItemRun implements Callable { OutGivingNodeProject.Status result; long time = SystemClock.now(); String fileSize = FileUtil.readableFileSize(file); + this.fileName = StrUtil.emptyToDefault(this.fileName, this.file.getName()); try { if (this.outGivingNodeProject.getDisabled() != null && this.outGivingNodeProject.getDisabled()) { // 禁用 @@ -84,7 +87,7 @@ public class OutGivingItemRun implements Callable { } this.updateStatus(this.outGivingId, OutGivingNodeProject.Status.Ing, I18nMessageUtil.get("i18n.start_distribution.bce5")); // - JsonMessage jsonMessage = OutGivingRun.fileUpload(file, this.secondaryDirectory, + JsonMessage jsonMessage = OutGivingRun.fileUpload(file, this.fileName, this.secondaryDirectory, this.outGivingNodeProject.getProjectId(), unzip, afterOpt, diff --git a/modules/server/src/main/java/org/dromara/jpom/outgiving/OutGivingRun.java b/modules/server/src/main/java/org/dromara/jpom/outgiving/OutGivingRun.java index a82502129..f227f36fc 100644 --- a/modules/server/src/main/java/org/dromara/jpom/outgiving/OutGivingRun.java +++ b/modules/server/src/main/java/org/dromara/jpom/outgiving/OutGivingRun.java @@ -80,6 +80,7 @@ public class OutGivingRun { private UserModel userModel; private boolean unzip; private int stripComponents; + private String fileName; /** * 分发方式 * upload: "手动上传", @@ -195,6 +196,7 @@ public class OutGivingRun { final OutGivingNodeProject outGivingNodeProject = outGivingNodeProjects.get(nowIndex); final OutGivingItemRun outGivingRun = new OutGivingItemRun(item, outGivingNodeProject, file, unzip, sleepTime); outGivingRun.setStripComponents(stripComponents); + outGivingRun.setFileName(fileName); OutGivingNodeProject.Status status = outGivingRun.call(); if (status != OutGivingNodeProject.Status.Ok) { if (afterOpt == AfterOpt.Order_Must_Restart) { @@ -221,6 +223,7 @@ public class OutGivingRun { for (final OutGivingNodeProject outGivingNodeProject : outGivingNodeProjects) { final OutGivingItemRun outGivingItemRun = new OutGivingItemRun(item, outGivingNodeProject, file, unzip, null); outGivingItemRun.setStripComponents(stripComponents); + outGivingItemRun.setFileName(fileName); syncFinisher.addWorker(() -> { try { statusList.add(outGivingItemRun.call()); @@ -378,14 +381,14 @@ public class OutGivingRun { * @param closeFirst 保存项目文件前先关闭项目 * @return json */ - public static JsonMessage fileUpload(File file, String levelName, String projectId, + public static JsonMessage fileUpload(File file, String fileName, String levelName, String projectId, boolean unzip, AfterOpt afterOpt, NodeModel nodeModel, boolean clearOld, Boolean closeFirst, BiConsumer streamProgress) { - return fileUpload(file, levelName, projectId, unzip, afterOpt, nodeModel, clearOld, null, closeFirst, streamProgress); + return fileUpload(file, fileName, levelName, projectId, unzip, afterOpt, nodeModel, clearOld, null, closeFirst, streamProgress); } /** @@ -402,7 +405,7 @@ public class OutGivingRun { * @param closeFirst 保存项目文件前先关闭项目 * @return json */ - public static JsonMessage fileUpload(File file, String levelName, String projectId, + public static JsonMessage fileUpload(File file, String fileName, String levelName, String projectId, boolean unzip, AfterOpt afterOpt, NodeModel nodeModel, @@ -410,7 +413,7 @@ public class OutGivingRun { Integer sleepTime, Boolean closeFirst, BiConsumer streamProgress) { - return fileUpload(file, levelName, projectId, unzip, afterOpt, nodeModel, clearOld, sleepTime, closeFirst, 0, streamProgress); + return fileUpload(file, fileName, levelName, projectId, unzip, afterOpt, nodeModel, clearOld, sleepTime, closeFirst, 0, streamProgress); } /** @@ -427,7 +430,10 @@ public class OutGivingRun { * @param closeFirst 保存项目文件前先关闭项目 * @return json */ - public static JsonMessage fileUpload(File file, String levelName, String projectId, + public static JsonMessage fileUpload(File file, + String fileName, + String levelName, + String projectId, boolean unzip, AfterOpt afterOpt, NodeModel nodeModel, @@ -457,6 +463,7 @@ public class OutGivingRun { data.put("closeFirst", closeFirst); try { return NodeForward.requestSharding(nodeModel, NodeUrl.Manage_File_Upload_Sharding, data, file, + fileName, sliceData -> { sliceData.putAll(data); return NodeForward.request(nodeModel, NodeUrl.Manage_File_Sharding_Merge, sliceData); diff --git a/web-vue/src/i18n/locales/en_us.json b/web-vue/src/i18n/locales/en_us.json index e325e565e..759e0f188 100644 --- a/web-vue/src/i18n/locales/en_us.json +++ b/web-vue/src/i18n/locales/en_us.json @@ -1768,6 +1768,7 @@ "i18n_9ee9d48699": "Modification is not supported after creation", "i18n_9f01272a10": " legal risk", "i18n_9f0de3800b": "Please fill in the warehouse name.", + "i18n_9f4a0d67c6": "It is recommended not to have blank spaces, tables, other blanks, \\,/,:, *,?, _ # # _,<,>, \\, in the file name| Waiting for special characters", "i18n_9f52492fbc": "For configuration details, please refer to the configuration example.", "i18n_9f6090c819": "The incoming parameters are: buildId, buildName, type, statusMsg, triggerTime", "i18n_9f6fa346d8": "Please enter an SSH name", diff --git a/web-vue/src/i18n/locales/zh_cn.json b/web-vue/src/i18n/locales/zh_cn.json index 0e79bda69..ecf8d4e56 100644 --- a/web-vue/src/i18n/locales/zh_cn.json +++ b/web-vue/src/i18n/locales/zh_cn.json @@ -1768,6 +1768,7 @@ "i18n_9ee9d48699": "创建后不支持修改", "i18n_9f01272a10": " 法律风险", "i18n_9f0de3800b": "请填写仓库名称", + "i18n_9f4a0d67c6": "文件名建议不要出现空白、制表、其他空白、\\、/、:、*、?、_##_、<、>、\\、| 等特殊字符", "i18n_9f52492fbc": "配置详情请参考配置示例", "i18n_9f6090c819": "传入参数有:buildId、buildName、type、statusMsg、triggerTime", "i18n_9f6fa346d8": "请输入 SSH 名称", diff --git a/web-vue/src/i18n/locales/zh_hk.json b/web-vue/src/i18n/locales/zh_hk.json index c4c5247ed..69fb61853 100644 --- a/web-vue/src/i18n/locales/zh_hk.json +++ b/web-vue/src/i18n/locales/zh_hk.json @@ -1768,6 +1768,7 @@ "i18n_9ee9d48699":"創建後不支持修改", "i18n_9f01272a10":" 法律風險", "i18n_9f0de3800b":"請填寫倉庫名稱", + "i18n_9f4a0d67c6":"文件名建議不要出現空白、製表、其他空白、\\、/、:、*、?、_##_、<、>、\\、| 等特殊字符", "i18n_9f52492fbc":"配置詳情請參考配置示例", "i18n_9f6090c819":"傳入參數有:buildId、buildName、type、statusMsg、triggerTime", "i18n_9f6fa346d8":"請輸入 SSH 名稱", diff --git a/web-vue/src/i18n/locales/zh_tw.json b/web-vue/src/i18n/locales/zh_tw.json index 437b7965e..6925c1fea 100644 --- a/web-vue/src/i18n/locales/zh_tw.json +++ b/web-vue/src/i18n/locales/zh_tw.json @@ -1768,6 +1768,7 @@ "i18n_9ee9d48699":"建立後不支援修改", "i18n_9f01272a10":" 法律風險", "i18n_9f0de3800b":"請填寫倉庫名稱", + "i18n_9f4a0d67c6":"檔名建議不要出現空白、製表、其他空白、\\、/、:、*、?、_##_、<、>、\\、| 等特殊字元", "i18n_9f52492fbc":"配置詳情請參考配置示例", "i18n_9f6090c819":"傳入引數有:buildId、buildName、type、statusMsg、triggerTime", "i18n_9f6fa346d8":"請輸入 SSH 名稱", diff --git a/web-vue/src/pages/file-manager/fileStorage/list.vue b/web-vue/src/pages/file-manager/fileStorage/list.vue index 41285d51c..6aef0aad8 100644 --- a/web-vue/src/pages/file-manager/fileStorage/list.vue +++ b/web-vue/src/pages/file-manager/fileStorage/list.vue @@ -217,6 +217,8 @@ + +