From 34c73d2e2662be27a3aa2d2dd978af1c6a64105b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E9=A1=BE=E5=90=9B=E7=A6=B9?= <2673609096@qq.com> Date: Sat, 16 Aug 2025 16:39:21 +0800 Subject: [PATCH] =?UTF-8?q?farm=E6=A8=A1=E5=9D=97-=E6=89=B9=E9=87=8F?= =?UTF-8?q?=E4=B8=8A=E4=BC=A0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../controller/admin/file/FileController.java | 6 +++ .../infra/service/file/FileService.java | 11 +++++ .../infra/service/file/FileServiceImpl.java | 45 +++++++++++++++++++ 3 files changed, 62 insertions(+) diff --git a/yudao-module-infra/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/file/FileController.java b/yudao-module-infra/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/file/FileController.java index afcf7162..1f5f0f93 100644 --- a/yudao-module-infra/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/file/FileController.java +++ b/yudao-module-infra/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/file/FileController.java @@ -50,6 +50,12 @@ public class FileController { uploadReqVO.getDirectory(), file.getContentType())); } + @PostMapping("/upload-multi") + @Operation(summary = "多文件上传", description = "批量上传多个文件") + public CommonResult uploadMultiFiles(@Valid FileMultiUploadReqVO uploadReqVO) throws Exception { + return success(fileService.createFiles(uploadReqVO.getFiles(), uploadReqVO.getDirectory())); + } + @GetMapping("/presigned-url") @Operation(summary = "获取文件预签名地址", description = "模式二:前端上传文件:用于前端直接上传七牛、阿里云 OSS 等文件存储器") @Parameters({ diff --git a/yudao-module-infra/src/main/java/cn/iocoder/yudao/module/infra/service/file/FileService.java b/yudao-module-infra/src/main/java/cn/iocoder/yudao/module/infra/service/file/FileService.java index 5b15ad87..13e36bb8 100644 --- a/yudao-module-infra/src/main/java/cn/iocoder/yudao/module/infra/service/file/FileService.java +++ b/yudao-module-infra/src/main/java/cn/iocoder/yudao/module/infra/service/file/FileService.java @@ -4,8 +4,10 @@ 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.FileMultiUploadRespVO; import cn.iocoder.yudao.module.infra.dal.dataobject.file.FileDO; import jakarta.validation.constraints.NotEmpty; +import org.springframework.web.multipart.MultipartFile; import java.util.List; @@ -36,6 +38,15 @@ public interface FileService { String createFile(@NotEmpty(message = "文件内容不能为空") byte[] content, String name, String directory, String type); + /** + * 批量上传文件 + * + * @param files 文件列表 + * @param directory 目录,允许空 + * @return 多文件上传结果 + */ + FileMultiUploadRespVO createFiles(List files, String directory); + /** * 生成文件预签名地址信息 * diff --git a/yudao-module-infra/src/main/java/cn/iocoder/yudao/module/infra/service/file/FileServiceImpl.java b/yudao-module-infra/src/main/java/cn/iocoder/yudao/module/infra/service/file/FileServiceImpl.java index 98447fb3..65bf90bd 100644 --- a/yudao-module-infra/src/main/java/cn/iocoder/yudao/module/infra/service/file/FileServiceImpl.java +++ b/yudao-module-infra/src/main/java/cn/iocoder/yudao/module/infra/service/file/FileServiceImpl.java @@ -2,14 +2,19 @@ package cn.iocoder.yudao.module.infra.service.file; import cn.hutool.core.date.LocalDateTimeUtil; import cn.hutool.core.io.FileUtil; +import cn.hutool.core.io.IoUtil; import cn.hutool.core.lang.Assert; import cn.hutool.core.util.StrUtil; import cn.hutool.crypto.digest.DigestUtil; +import org.springframework.web.multipart.MultipartFile; + +import java.util.ArrayList; import cn.iocoder.yudao.framework.common.pojo.PageResult; 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.FileMultiUploadRespVO; 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; @@ -92,6 +97,46 @@ public class FileServiceImpl implements FileService { return url; } + @Override + @SneakyThrows + public FileMultiUploadRespVO createFiles(List files, String directory) { + FileMultiUploadRespVO result = new FileMultiUploadRespVO(); + List successFiles = new ArrayList<>(); + List failedFiles = new ArrayList<>(); + + for (MultipartFile file : files) { + FileMultiUploadRespVO.FileUploadResult fileResult = new FileMultiUploadRespVO.FileUploadResult(); + fileResult.setOriginalName(file.getOriginalFilename()); + fileResult.setSize(file.getSize()); + fileResult.setType(file.getContentType()); + + try { + // 上传文件 + byte[] content = IoUtil.readBytes(file.getInputStream()); + String url = createFile(content, file.getOriginalFilename(), directory, file.getContentType()); + + // 设置成功结果 + fileResult.setUrl(url); + fileResult.setSuccess(true); + successFiles.add(fileResult); + } catch (Exception e) { + // 设置失败结果 + fileResult.setSuccess(false); + fileResult.setErrorMessage(e.getMessage()); + failedFiles.add(fileResult); + } + } + + // 设置统计信息 + result.setSuccessFiles(successFiles); + result.setFailedFiles(failedFiles); + result.setTotalCount(files.size()); + result.setSuccessCount(successFiles.size()); + result.setFailedCount(failedFiles.size()); + + return result; + } + @VisibleForTesting String generateUploadPath(String name, String directory) { // 1. 生成前缀、后缀