From 3328aae4e394d3ecf2c4c3e5c035af6a8c77c70f Mon Sep 17 00:00:00 2001 From: old burden Date: Mon, 13 Apr 2026 17:15:43 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20=E4=B8=8A=E4=BC=A0=E6=8E=A5=E5=8F=A3?= =?UTF-8?q?=E5=81=9A=E4=BC=98=E5=8C=96=EF=BC=88=E7=9B=AE=E5=89=8D=E5=8F=AA?= =?UTF-8?q?=E4=BD=BF=E7=94=A8=E4=BA=86/api/file/upload=EF=BC=8C=E5=85=B6?= =?UTF-8?q?=E4=BB=96=E6=8E=A5=E5=8F=A3=E5=89=8D=E7=AB=AF=E6=B2=A1=E4=BD=BF?= =?UTF-8?q?=E7=94=A8)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../java/com/ruoyi/api/CosController.java | 10 +++++-- .../java/com/ruoyi/api/FileController.java | 17 ++++++++--- .../controller/common/CommonController.java | 8 +++-- .../ruoyi/common/utils/TencentCosUtil.java | 29 +++++++++++++++---- 4 files changed, 50 insertions(+), 14 deletions(-) diff --git a/web-api/ruoyi-admin/src/main/java/com/ruoyi/api/CosController.java b/web-api/ruoyi-admin/src/main/java/com/ruoyi/api/CosController.java index d188e10..470f9fa 100644 --- a/web-api/ruoyi-admin/src/main/java/com/ruoyi/api/CosController.java +++ b/web-api/ruoyi-admin/src/main/java/com/ruoyi/api/CosController.java @@ -1,6 +1,7 @@ package com.ruoyi.api; import com.ruoyi.common.core.domain.AjaxResult; +import com.ruoyi.common.utils.StringUtils; import com.ruoyi.common.utils.TencentCosUtil; import io.swagger.annotations.Api; import io.swagger.annotations.ApiOperation; @@ -28,11 +29,16 @@ public class CosController { @PostMapping("/upload") public AjaxResult upload( @ApiParam(name = "file", value = "文件", required = true) - @RequestParam("file") MultipartFile file) throws Exception { - String uploadUrl = tencentCosUtil.uploadMultipartFile(file, true); + @RequestParam("file") MultipartFile file, + @ApiParam(name = "prefix", value = "路径前缀(如asset)", required = false) + @RequestParam(value = "prefix", required = false) String prefix) throws Exception { + String uploadUrl = tencentCosUtil.uploadMultipartFile(file, true, prefix); AjaxResult ajax = AjaxResult.success(uploadUrl); ajax.put("url", uploadUrl); ajax.put("oldName", file.getOriginalFilename()); + if (StringUtils.isNotBlank(prefix)) { + ajax.put("prefix", prefix); + } return ajax; } } diff --git a/web-api/ruoyi-admin/src/main/java/com/ruoyi/api/FileController.java b/web-api/ruoyi-admin/src/main/java/com/ruoyi/api/FileController.java index 2dcc9bb..1a76d97 100644 --- a/web-api/ruoyi-admin/src/main/java/com/ruoyi/api/FileController.java +++ b/web-api/ruoyi-admin/src/main/java/com/ruoyi/api/FileController.java @@ -1,6 +1,7 @@ package com.ruoyi.api; import com.ruoyi.common.core.domain.AjaxResult; +import com.ruoyi.common.utils.StringUtils; import com.ruoyi.common.utils.TencentCosUtil; import io.swagger.annotations.Api; import io.swagger.annotations.ApiOperation; @@ -21,17 +22,25 @@ public class FileController { private final TencentCosUtil tencentCosUtil; /** - * 文件上传 + * 文件上传(支持prefix路径前缀) */ - @ApiOperation(value = "文件上传") @PostMapping("/upload") public AjaxResult upload( @ApiParam(name = "file", value = "文件", required = true) - @RequestParam("file") MultipartFile file) throws Exception { + @RequestParam("file") MultipartFile file, + @ApiParam(name = "prefix", value = "路径前缀(如asset、generated等)", required = false) + @RequestParam(value = "prefix", required = false) String prefix) throws Exception { + AjaxResult ajax = AjaxResult.success(); - String uploadUrl = tencentCosUtil.uploadMultipartFile(file, true); + String uploadUrl = tencentCosUtil.uploadMultipartFile(file, true, prefix); + ajax.put("url", uploadUrl); + ajax.put("oldName", file.getOriginalFilename()); + if (StringUtils.isNotBlank(prefix)) { + ajax.put("prefix", prefix); + } + return ajax; } diff --git a/web-api/ruoyi-admin/src/main/java/com/ruoyi/web/controller/common/CommonController.java b/web-api/ruoyi-admin/src/main/java/com/ruoyi/web/controller/common/CommonController.java index 0f2ff29..9277e82 100644 --- a/web-api/ruoyi-admin/src/main/java/com/ruoyi/web/controller/common/CommonController.java +++ b/web-api/ruoyi-admin/src/main/java/com/ruoyi/web/controller/common/CommonController.java @@ -142,16 +142,20 @@ public class CommonController { } @PostMapping("/cos/upload") - public AjaxResult uploadCover(MultipartFile file) { + public AjaxResult uploadCover(MultipartFile file, + @RequestParam(value = "prefix", required = false) String prefix) { AjaxResult ajax = AjaxResult.success(); String uploadUrl; try { - uploadUrl = tencentCosUtil.upload(file); + uploadUrl = tencentCosUtil.uploadMultipartFile(file, true, prefix); } catch (Exception e) { throw new BaseException("上传失败"); } ajax.put("url", uploadUrl); ajax.put("oldName", file.getOriginalFilename()); + if (StringUtils.isNotBlank(prefix)) { + ajax.put("prefix", prefix); + } return ajax; } diff --git a/web-api/ruoyi-common/src/main/java/com/ruoyi/common/utils/TencentCosUtil.java b/web-api/ruoyi-common/src/main/java/com/ruoyi/common/utils/TencentCosUtil.java index 5a27fde..a59910f 100644 --- a/web-api/ruoyi-common/src/main/java/com/ruoyi/common/utils/TencentCosUtil.java +++ b/web-api/ruoyi-common/src/main/java/com/ruoyi/common/utils/TencentCosUtil.java @@ -60,7 +60,14 @@ public class TencentCosUtil { * 与AwsS3Util.uploadMultipartFile方法接口兼容 */ public String upload(MultipartFile file) throws Exception { - return uploadMultipartFile(file, true); + return uploadMultipartFile(file, true, null); + } + + /** + * 兼容原有调用(保留双参数版本) + */ + public String uploadMultipartFile(MultipartFile file, boolean isPublic) throws Exception { + return uploadMultipartFile(file, isPublic, null); } /** @@ -68,15 +75,16 @@ public class TencentCosUtil { * * @param file 前端上传的MultipartFile * @param isPublic 是否公开访问(当前实现中忽略,使用domain配置) + * @param prefix 自定义路径前缀(如 "asset"),null或空时不添加前缀 * @return 文件访问地址(URL字符串) */ - public String uploadMultipartFile(MultipartFile file, boolean isPublic) throws Exception { + public String uploadMultipartFile(MultipartFile file, boolean isPublic, String prefix) throws Exception { if (file.isEmpty()) { throw new IllegalArgumentException("上传文件不能为空"); } - // 生成唯一文件键,格式与AWS一致:yyyy/MM/dd/uuid_filename - String key = generateCosKey(file.getOriginalFilename()); + // 生成唯一文件键,支持prefix参数 + String key = generateCosKey(file.getOriginalFilename(), prefix); try { InputStream inputStream = file.getInputStream(); @@ -145,11 +153,20 @@ public class TencentCosUtil { } /** - * 生成COS文件键,与AWS保持一致的命名格式 + * 生成COS文件键,支持prefix前缀 + * prefix=asset → asset/yyyy/MM/dd/xxxxxxxx_filename + * prefix=null或空 → yyyy/MM/dd/xxxxxxxx_filename */ - private String generateCosKey(String originalFileName) { + private String generateCosKey(String originalFileName, String prefix) { String uuid = UUID.randomUUID().toString().replaceAll("-", "").substring(0, 8); String dateTime = new DateTime().toString("yyyy/MM/dd"); + + if (StringUtils.isNotBlank(prefix)) { + // 清理prefix,防止出现多余斜杠 + String cleanPrefix = prefix.trim().replaceAll("^/+|/+$", ""); + return cleanPrefix + "/" + dateTime + "/" + uuid + "_" + originalFileName; + } + return dateTime + "/" + uuid + "_" + originalFileName; }