From 731c4425d41981e774dc4e378c541ae47ea5b95f Mon Sep 17 00:00:00 2001 From: wangrunpu <2095588299@qq.com> Date: Fri, 30 Jan 2026 14:56:30 +0800 Subject: [PATCH] =?UTF-8?q?fix:=20=E4=BF=AE=E6=94=B9=E4=B8=8A=E4=BC=A0?= =?UTF-8?q?=E6=96=87=E4=BB=B6=E6=8E=A5=E5=8F=A3=E7=9A=84=E8=BF=94=E5=9B=9E?= =?UTF-8?q?=E5=80=BC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../controller/admin/file/FileController.java | 4 +-- .../admin/file/vo/file/FileUploadRespVO.java | 24 +++++++++++++ .../infra/service/file/FileService.java | 16 +++++++-- .../infra/service/file/FileServiceImpl.java | 35 +++++++++++++++++++ .../DustClearrecordMapper.java | 2 +- 5 files changed, 75 insertions(+), 6 deletions(-) create mode 100644 yudao-module-infra/yudao-module-infra-server/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/file/vo/file/FileUploadRespVO.java diff --git a/yudao-module-infra/yudao-module-infra-server/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/file/FileController.java b/yudao-module-infra/yudao-module-infra-server/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/file/FileController.java index ca7db6407..0f3f69f8f 100644 --- a/yudao-module-infra/yudao-module-infra-server/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/file/FileController.java +++ b/yudao-module-infra/yudao-module-infra-server/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/file/FileController.java @@ -47,10 +47,10 @@ public class FileController { @Operation(summary = "上传文件", description = "模式一:后端上传文件") @Parameter(name = "file", description = "文件附件", required = true, schema = @Schema(type = "string", format = "binary")) - public CommonResult uploadFile(@Valid FileUploadReqVO uploadReqVO) throws Exception { + public CommonResult uploadFile(@Valid FileUploadReqVO uploadReqVO) throws Exception { MultipartFile file = uploadReqVO.getFile(); byte[] content = IoUtil.readBytes(file.getInputStream()); - return success(fileService.createFile(content, file.getOriginalFilename(), + return success(fileService.createFileWithInfo(content, file.getOriginalFilename(), uploadReqVO.getDirectory(), file.getContentType())); } diff --git a/yudao-module-infra/yudao-module-infra-server/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/file/vo/file/FileUploadRespVO.java b/yudao-module-infra/yudao-module-infra-server/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/file/vo/file/FileUploadRespVO.java new file mode 100644 index 000000000..c7d2d9d81 --- /dev/null +++ b/yudao-module-infra/yudao-module-infra-server/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/file/vo/file/FileUploadRespVO.java @@ -0,0 +1,24 @@ +package cn.iocoder.yudao.module.infra.controller.admin.file.vo.file; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; + +@Schema(description = "管理后台 - 上传文件 Response VO") +@Data +@NoArgsConstructor +@AllArgsConstructor +public class FileUploadRespVO { + + @Schema(description = "文件ID", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024") + private Long id; + + @Schema(description = "文件URL", requiredMode = Schema.RequiredMode.REQUIRED, + example = "https://www.iocoder.cn/yudao.jpg") + private String url; + + @Schema(description = "文件路径", example = "2024/01/file.jpg") + private String path; + +} diff --git a/yudao-module-infra/yudao-module-infra-server/src/main/java/cn/iocoder/yudao/module/infra/service/file/FileService.java b/yudao-module-infra/yudao-module-infra-server/src/main/java/cn/iocoder/yudao/module/infra/service/file/FileService.java index 421bbe8d4..4370cc286 100644 --- a/yudao-module-infra/yudao-module-infra-server/src/main/java/cn/iocoder/yudao/module/infra/service/file/FileService.java +++ b/yudao-module-infra/yudao-module-infra-server/src/main/java/cn/iocoder/yudao/module/infra/service/file/FileService.java @@ -1,9 +1,7 @@ package cn.iocoder.yudao.module.infra.service.file; import cn.iocoder.yudao.framework.common.pojo.PageResult; -import cn.iocoder.yudao.module.infra.controller.admin.file.vo.file.FileCreateReqVO; -import cn.iocoder.yudao.module.infra.controller.admin.file.vo.file.FilePageReqVO; -import cn.iocoder.yudao.module.infra.controller.admin.file.vo.file.FilePresignedUrlRespVO; +import cn.iocoder.yudao.module.infra.controller.admin.file.vo.file.*; import cn.iocoder.yudao.module.infra.dal.dataobject.file.FileDO; import jakarta.validation.constraints.NotEmpty; @@ -36,6 +34,18 @@ public interface FileService { String createFile(@NotEmpty(message = "文件内容不能为空") byte[] content, String name, String directory, String type); + /** + * 保存文件,返回ID和URL + * + * @param content 文件内容 + * @param name 文件名称 + * @param directory 目录 + * @param type MIME类型 + * @return 文件信息 + */ + FileUploadRespVO createFileWithInfo(@NotEmpty(message = "文件内容不能为空") byte[] content, + String name, String directory, String type); + /** * 生成文件预签名地址信息,用于上传 * diff --git a/yudao-module-infra/yudao-module-infra-server/src/main/java/cn/iocoder/yudao/module/infra/service/file/FileServiceImpl.java b/yudao-module-infra/yudao-module-infra-server/src/main/java/cn/iocoder/yudao/module/infra/service/file/FileServiceImpl.java index b4f4282d5..c8a1f1ec9 100644 --- a/yudao-module-infra/yudao-module-infra-server/src/main/java/cn/iocoder/yudao/module/infra/service/file/FileServiceImpl.java +++ b/yudao-module-infra/yudao-module-infra-server/src/main/java/cn/iocoder/yudao/module/infra/service/file/FileServiceImpl.java @@ -11,6 +11,7 @@ import cn.iocoder.yudao.framework.common.util.object.BeanUtils; import cn.iocoder.yudao.module.infra.controller.admin.file.vo.file.FileCreateReqVO; import cn.iocoder.yudao.module.infra.controller.admin.file.vo.file.FilePageReqVO; import cn.iocoder.yudao.module.infra.controller.admin.file.vo.file.FilePresignedUrlRespVO; +import cn.iocoder.yudao.module.infra.controller.admin.file.vo.file.FileUploadRespVO; import cn.iocoder.yudao.module.infra.dal.dataobject.file.FileDO; import cn.iocoder.yudao.module.infra.dal.mysql.file.FileMapper; import cn.iocoder.yudao.module.infra.framework.file.core.client.FileClient; @@ -91,6 +92,40 @@ public class FileServiceImpl implements FileService { return url; } + @Override + @SneakyThrows + public FileUploadRespVO createFileWithInfo(byte[] content, String name, String directory, String type) { + // 1.1 处理 type 为空的情况 + if (StrUtil.isEmpty(type)) { + type = FileTypeUtils.getMineType(content, name); + } + // 1.2 处理 name 为空的情况 + if (StrUtil.isEmpty(name)) { + name = DigestUtil.sha256Hex(content); + } + if (StrUtil.isEmpty(FileUtil.extName(name))) { + // 如果 name 没有后缀 type,则补充后缀 + String extension = FileTypeUtils.getExtension(type); + if (StrUtil.isNotEmpty(extension)) { + name = name + extension; + } + } + + // 2.1 生成上传的 path,需要保证唯一 + String path = generateUploadPath(name, directory); + // 2.2 上传到文件存储器 + FileClient client = fileConfigService.getMasterFileClient(); + Assert.notNull(client, "客户端(master) 不能为空"); + String url = client.upload(content, path, type); + // 3. 保存到数据库 + FileDO fileDO = new FileDO().setConfigId(client.getId()) + .setName(name).setPath(path).setUrl(url) + .setType(type).setSize((long) content.length); + fileMapper.insert(fileDO); + // 4. 返回文件信息(包含ID) + return new FileUploadRespVO(fileDO.getId(), url, path); + } + @VisibleForTesting String generateUploadPath(String name, String directory) { // 1. 生成前缀、后缀 diff --git a/yudao-module-system/yudao-module-system-server/src/main/java/cn/iocoder/yudao/module/system/dal/mysql/dustclearrecord/DustClearrecordMapper.java b/yudao-module-system/yudao-module-system-server/src/main/java/cn/iocoder/yudao/module/system/dal/mysql/dustclearrecord/DustClearrecordMapper.java index 02576d53d..840e9293d 100644 --- a/yudao-module-system/yudao-module-system-server/src/main/java/cn/iocoder/yudao/module/system/dal/mysql/dustclearrecord/DustClearrecordMapper.java +++ b/yudao-module-system/yudao-module-system-server/src/main/java/cn/iocoder/yudao/module/system/dal/mysql/dustclearrecord/DustClearrecordMapper.java @@ -22,7 +22,7 @@ public interface DustClearrecordMapper extends BaseMapperX { .eqIfPresent(DustClearrecordDO::getDataId, reqVO.getDataId()) .likeIfPresent(DustClearrecordDO::getClearItemName, reqVO.getClearItemName()) .eqIfPresent(DustClearrecordDO::getTaskProcess, reqVO.getTaskProcess()) - .eqIfPresent(DustClearrecordDO::getTaskPerson, reqVO.getTaskPerson()) + .likeIfPresent(DustClearrecordDO::getTaskPerson, reqVO.getTaskPerson()) .betweenIfPresent(DustClearrecordDO::getTaskTime, reqVO.getTaskTime()) .betweenIfPresent(DustClearrecordDO::getCreateTime, reqVO.getCreateTime()) .eqIfPresent(DustClearrecordDO::getPicOssId, reqVO.getPicOssId())