From d724f23d36463328e2d661c6fc1fcdf77d8b3a47 Mon Sep 17 00:00:00 2001 From: furongxin <419481438@qq.com> Date: Wed, 26 Jun 2024 15:12:10 +0800 Subject: [PATCH] =?UTF-8?q?=E6=96=B0=E5=A2=9E=20=E7=94=A8=E6=88=B7?= =?UTF-8?q?=E6=96=87=E4=BB=B6=E4=B8=8A=E4=BC=A0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../yudao/module/infra/api/file/FileApi.java | 16 ++-- .../api/file/dto/UserFileUpdateReqDTO.java | 20 +++++ .../module/infra/api/file/FileApiImpl.java | 11 +++ .../controller/admin/file/FileController.java | 16 ++++ .../file/vo/file/UserFileUpdateReqVO.java | 20 +++++ .../infra/dal/dataobject/file/UserFileDO.java | 57 +++++++++++++ .../infra/dal/mysql/file/UserFileMapper.java | 9 +++ .../infra/service/file/FileService.java | 22 +++++ .../infra/service/file/FileServiceImpl.java | 80 ++++++++++++++++++- 9 files changed, 239 insertions(+), 12 deletions(-) create mode 100644 yudao-module-infra/yudao-module-infra-api/src/main/java/cn/iocoder/yudao/module/infra/api/file/dto/UserFileUpdateReqDTO.java create mode 100644 yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/file/vo/file/UserFileUpdateReqVO.java create mode 100644 yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/dal/dataobject/file/UserFileDO.java create mode 100644 yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/dal/mysql/file/UserFileMapper.java diff --git a/yudao-module-infra/yudao-module-infra-api/src/main/java/cn/iocoder/yudao/module/infra/api/file/FileApi.java b/yudao-module-infra/yudao-module-infra-api/src/main/java/cn/iocoder/yudao/module/infra/api/file/FileApi.java index 44d7e1d7..f849fa1c 100644 --- a/yudao-module-infra/yudao-module-infra-api/src/main/java/cn/iocoder/yudao/module/infra/api/file/FileApi.java +++ b/yudao-module-infra/yudao-module-infra-api/src/main/java/cn/iocoder/yudao/module/infra/api/file/FileApi.java @@ -2,20 +2,16 @@ package cn.iocoder.yudao.module.infra.api.file; import cn.iocoder.yudao.framework.common.pojo.CommonResult; import cn.iocoder.yudao.module.infra.api.file.dto.FileCreateReqDTO; +import cn.iocoder.yudao.module.infra.api.file.dto.UserFileUpdateReqDTO; import cn.iocoder.yudao.module.infra.enums.ApiConstants; +import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.Parameter; import io.swagger.v3.oas.annotations.tags.Tag; -import io.swagger.v3.oas.annotations.Operation; import org.springframework.cloud.openfeign.FeignClient; -import org.springframework.web.bind.annotation.DeleteMapping; -import org.springframework.web.bind.annotation.PostMapping; -import org.springframework.web.bind.annotation.RequestBody; -import org.springframework.web.bind.annotation.RequestParam; +import org.springframework.web.bind.annotation.*; import javax.validation.Valid; -import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; - @FeignClient(name = ApiConstants.NAME) // TODO 芋艿:fallbackFactory = @Tag(name = "RPC 服务 - 文件") public interface FileApi { @@ -80,8 +76,12 @@ public interface FileApi { @RequestParam("name") String name, @RequestBody byte[] content) ; - @DeleteMapping("/deleteBpmFile") + @DeleteMapping(PREFIX + "/deleteBpmFile") @Operation(summary = "删除工作流附件") @Parameter(name = "url", description = "附件URL地址", required = true) CommonResult deleteBpmFile(@RequestParam("url") String url) throws Exception; + + @PutMapping(PREFIX + "/updateUserFile") + @Operation(summary = "修改用户文件绑定 用户编号") + CommonResult updateUserFileUserId(@RequestBody UserFileUpdateReqDTO updateReqVO); } diff --git a/yudao-module-infra/yudao-module-infra-api/src/main/java/cn/iocoder/yudao/module/infra/api/file/dto/UserFileUpdateReqDTO.java b/yudao-module-infra/yudao-module-infra-api/src/main/java/cn/iocoder/yudao/module/infra/api/file/dto/UserFileUpdateReqDTO.java new file mode 100644 index 00000000..5e71b34b --- /dev/null +++ b/yudao-module-infra/yudao-module-infra-api/src/main/java/cn/iocoder/yudao/module/infra/api/file/dto/UserFileUpdateReqDTO.java @@ -0,0 +1,20 @@ +package cn.iocoder.yudao.module.infra.api.file.dto; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +import javax.validation.constraints.NotNull; +import java.util.List; + +@Schema(description = "RPC 服务 - 用户文件 Request DTO") +@Data +public class UserFileUpdateReqDTO { + + @Schema(description = "附件地址", requiredMode = Schema.RequiredMode.REQUIRED) + @NotNull(message = "附件地址不能为空") + private List urls; + + @Schema(description = "用户编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") + @NotNull(message = "用户编号不能为空") + private Long userId; +} diff --git a/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/api/file/FileApiImpl.java b/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/api/file/FileApiImpl.java index 63532cc4..c59226f4 100644 --- a/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/api/file/FileApiImpl.java +++ b/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/api/file/FileApiImpl.java @@ -1,8 +1,11 @@ package cn.iocoder.yudao.module.infra.api.file; import cn.iocoder.yudao.framework.common.pojo.CommonResult; +import cn.iocoder.yudao.framework.common.util.object.BeanUtils; import cn.iocoder.yudao.module.infra.api.file.dto.FileCreateReqDTO; +import cn.iocoder.yudao.module.infra.api.file.dto.UserFileUpdateReqDTO; import cn.iocoder.yudao.module.infra.controller.admin.file.vo.file.BpmFileUploadReqVO; +import cn.iocoder.yudao.module.infra.controller.admin.file.vo.file.UserFileUpdateReqVO; import cn.iocoder.yudao.module.infra.service.file.FileService; import org.springframework.validation.annotation.Validated; import org.springframework.web.bind.annotation.RestController; @@ -59,4 +62,12 @@ public class FileApiImpl implements FileApi { return success(true); } + + @Override + public CommonResult updateUserFileUserId(UserFileUpdateReqDTO updateReqVO) { + + UserFileUpdateReqVO reqVO = BeanUtils.toBean(updateReqVO, UserFileUpdateReqVO.class); + fileService.updateUserFileUserId(reqVO); + return success(true); + } } diff --git a/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/file/FileController.java b/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/file/FileController.java index de905c33..13c24718 100644 --- a/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/file/FileController.java +++ b/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/file/FileController.java @@ -12,6 +12,7 @@ import cn.iocoder.yudao.module.infra.controller.admin.file.vo.file.*; import cn.iocoder.yudao.module.infra.dal.dataobject.file.BpmFileDO; import cn.iocoder.yudao.module.infra.dal.dataobject.file.BusinessFileDO; import cn.iocoder.yudao.module.infra.dal.dataobject.file.FileDO; +import cn.iocoder.yudao.module.infra.dal.dataobject.file.UserFileDO; import cn.iocoder.yudao.module.infra.service.file.FileService; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.Parameter; @@ -140,4 +141,19 @@ public class FileController { return "success" ; } //add by yj 2024 04-11 End + + @PostMapping("/userFileUpload") + @Operation(summary = "上传用户文件") + @OperateLog(logArgs = false) // 上传文件,没有记录操作日志的必要 + public CommonResult userFileUpload(@RequestParam("uploadFiles") MultipartFile file) { + return success(fileService.createUserReturnFile(file)); + } + + @DeleteMapping("/deleteUserFile") + @Operation(summary = "删除用户文件") + @Parameter(name = "url", description = "附件URL地址", required = true) + public CommonResult deleteUserFile(@RequestParam("url") String url) throws Exception { + fileService.deleteUserFile(url); + return success(true); + } } diff --git a/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/file/vo/file/UserFileUpdateReqVO.java b/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/file/vo/file/UserFileUpdateReqVO.java new file mode 100644 index 00000000..3b9636c7 --- /dev/null +++ b/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/file/vo/file/UserFileUpdateReqVO.java @@ -0,0 +1,20 @@ +package cn.iocoder.yudao.module.infra.controller.admin.file.vo.file; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +import javax.validation.constraints.NotNull; +import java.util.List; + +@Schema(description = "管理后台 - 用户文件绑定 用户编号 Request VO") +@Data +public class UserFileUpdateReqVO { + + @Schema(description = "附件地址", requiredMode = Schema.RequiredMode.REQUIRED) + @NotNull(message = "附件地址不能为空") + private List urls; + + @Schema(description = "用户编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") + @NotNull(message = "用户编号不能为空") + private Long userId; +} diff --git a/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/dal/dataobject/file/UserFileDO.java b/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/dal/dataobject/file/UserFileDO.java new file mode 100644 index 00000000..732d526f --- /dev/null +++ b/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/dal/dataobject/file/UserFileDO.java @@ -0,0 +1,57 @@ +package cn.iocoder.yudao.module.infra.dal.dataobject.file; + + +import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO; +import com.baomidou.mybatisplus.annotation.TableName; +import lombok.*; + +/** + * 文件表 + * 每次文件上传,都会记录一条记录到该表中 + * + */ +@TableName("system_user_file") +@Data +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) +@Builder +@NoArgsConstructor +@AllArgsConstructor +public class UserFileDO extends BaseDO { + + /** + * 编号,数据库自增 + */ + private Long id; + + /** + * 用户编号 + */ + private Long userId; + /** + * 配置编号 + * + * 关联 {@link FileConfigDO#getId()} + */ + private Long configId; + /** + * 原文件名 + */ + private String name; + /** + * 路径,即文件名 + */ + private String path; + /** + * 访问地址 + */ + private String url; + /** + * 文件的 MIME 类型,例如 "application/octet-stream" + */ + private String type; + /** + * 文件大小 + */ + private Integer size; +} diff --git a/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/dal/mysql/file/UserFileMapper.java b/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/dal/mysql/file/UserFileMapper.java new file mode 100644 index 00000000..91f9f750 --- /dev/null +++ b/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/dal/mysql/file/UserFileMapper.java @@ -0,0 +1,9 @@ +package cn.iocoder.yudao.module.infra.dal.mysql.file; + +import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; +import cn.iocoder.yudao.module.infra.dal.dataobject.file.UserFileDO; +import org.apache.ibatis.annotations.Mapper; + +@Mapper +public interface UserFileMapper extends BaseMapperX { +} diff --git a/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/service/file/FileService.java b/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/service/file/FileService.java index 8ec646b1..6cea8ece 100644 --- a/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/service/file/FileService.java +++ b/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/service/file/FileService.java @@ -4,9 +4,11 @@ import cn.iocoder.yudao.module.infra.controller.admin.file.vo.file.BpmFileUpload import cn.iocoder.yudao.module.infra.controller.admin.file.vo.file.BusinessFileUploadReqVO; import cn.iocoder.yudao.module.infra.controller.admin.file.vo.file.FilePageReqVO; import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.module.infra.controller.admin.file.vo.file.UserFileUpdateReqVO; import cn.iocoder.yudao.module.infra.dal.dataobject.file.BpmFileDO; import cn.iocoder.yudao.module.infra.dal.dataobject.file.BusinessFileDO; import cn.iocoder.yudao.module.infra.dal.dataobject.file.FileDO; +import cn.iocoder.yudao.module.infra.dal.dataobject.file.UserFileDO; import org.springframework.web.multipart.MultipartFile; /** @@ -127,4 +129,24 @@ public interface FileService { * @return */ String updateBusinessFileContent(String url, Long businessType, String name, byte[] content) ; + + /**3 + * 保存用户文件,并返回文件对象 + * + * @param file 上传文件对象 + * @return 文件路径 + */ + UserFileDO createUserReturnFile(MultipartFile file); + + /** + * 删除用户文件 + * @param url 文件URL地址 + */ + void deleteUserFile(String url); + + /** + * 更新用户文件 UserId + * @param updateReqVO 更新信息 + */ + void updateUserFileUserId(UserFileUpdateReqVO updateReqVO); } diff --git a/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/service/file/FileServiceImpl.java b/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/service/file/FileServiceImpl.java index 7658904e..561332e7 100644 --- a/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/service/file/FileServiceImpl.java +++ b/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/service/file/FileServiceImpl.java @@ -12,13 +12,12 @@ import cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils; import cn.iocoder.yudao.module.infra.controller.admin.file.vo.file.BpmFileUploadReqVO; import cn.iocoder.yudao.module.infra.controller.admin.file.vo.file.BusinessFileUploadReqVO; import cn.iocoder.yudao.module.infra.controller.admin.file.vo.file.FilePageReqVO; +import cn.iocoder.yudao.module.infra.controller.admin.file.vo.file.UserFileUpdateReqVO; import cn.iocoder.yudao.module.infra.dal.dataobject.file.BpmFileDO; import cn.iocoder.yudao.module.infra.dal.dataobject.file.BusinessFileDO; import cn.iocoder.yudao.module.infra.dal.dataobject.file.FileDO; -import cn.iocoder.yudao.module.infra.dal.mysql.file.BpmFileMapper; -import cn.iocoder.yudao.module.infra.dal.mysql.file.BusinessFileMapper; -import cn.iocoder.yudao.module.infra.dal.mysql.file.FileContentMapper; -import cn.iocoder.yudao.module.infra.dal.mysql.file.FileMapper; +import cn.iocoder.yudao.module.infra.dal.dataobject.file.UserFileDO; +import cn.iocoder.yudao.module.infra.dal.mysql.file.*; import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper; import lombok.SneakyThrows; import org.springframework.stereotype.Service; @@ -50,6 +49,9 @@ public class FileServiceImpl implements FileService { @Resource private FileContentMapper fileContentMapper; + @Resource + private UserFileMapper userFileMapper; + @Override public PageResult getFilePage(FilePageReqVO pageReqVO) { return fileMapper.selectPage(pageReqVO); @@ -396,4 +398,74 @@ public class FileServiceImpl implements FileService { } return url ; } + + @Override + @SneakyThrows + public UserFileDO createUserReturnFile(MultipartFile file) { + + long timestamp = System.currentTimeMillis(); + + String name = file.getOriginalFilename(); + String path = null; + byte[] content = IoUtil.readBytes(file.getInputStream()); + + // 计算默认的 path 名 + String type = FileTypeUtils.getMineType(content, name); + + // 如果 name 为空,则使用 path 填充 + if (!StrUtil.isEmpty(name)) { + String beginPath = name.split("\\.")[0]; + path = beginPath + "_" + timestamp + "." + FileNameUtil.extName(name); + }else { + name = "File" + timestamp; + path = name; + } + + // 上传到文件存储器 + FileClient client = fileConfigService.getMasterFileClient(); + Assert.notNull(client, "客户端(master) 不能为空"); + String url = client.upload(content, path, type); + + // 插入 system_user_file + UserFileDO fileDo = new UserFileDO(); + fileDo.setConfigId(client.getId()); + fileDo.setName(name); + fileDo.setPath(path); + fileDo.setUrl(url); + fileDo.setType(type); + fileDo.setSize(content.length); + userFileMapper.insert(fileDo); + + return fileDo; + } + + @Override + @SneakyThrows + public void deleteUserFile(String url) { + + String path = url.substring(url.lastIndexOf("/") + 1); + UserFileDO file = userFileMapper.selectOne(UserFileDO::getPath, path); + if (file == null) { + throw exception(FILE_NOT_EXISTS); + } + + // 从文件存储器中删除 + FileClient client = fileConfigService.getFileClient(file.getConfigId()); + Assert.notNull(client, "客户端({}) 不能为空", file.getConfigId()); + client.delete(file.getPath()); + + // 删除记录 + userFileMapper.deleteById(file.getId()); + } + + @Override + public void updateUserFileUserId(UserFileUpdateReqVO updateReqVO) { + + LambdaUpdateWrapper lambdaUpdateWrapper = new LambdaUpdateWrapper<>(); + lambdaUpdateWrapper.in(UserFileDO::getUrl, updateReqVO.getUrls()); + lambdaUpdateWrapper.set(UserFileDO::getUserId, updateReqVO.getUserId()); // 假设 bid 是要更新的 bid 值 + + // 调用 MyBatis Plus 的 update 方法执行批量更新 + userFileMapper.update(null, lambdaUpdateWrapper); + } }