From 09992e1887a34ab7fab91b27e9ea043bc9964e60 Mon Sep 17 00:00:00 2001 From: gulongcheng <474084054@qq.com> Date: Wed, 12 Nov 2025 18:08:37 +0800 Subject: [PATCH] =?UTF-8?q?minio=E5=88=86=E6=9D=83=E9=99=90=E5=AD=98?= =?UTF-8?q?=E5=82=A8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .idea/compiler.xml | 2 + .idea/encodings.xml | 1 + .../sdm/common/entity/enums/DirTypeEnum.java | 7 +- .../common/entity/enums/FileBizTypeEnum.java | 1 - .../feign/inter/data/IDataFeignClient.java | 6 +- data/pom.xml | 7 + .../java/com/sdm/data/config/MinioConfig.java | 37 ++-- .../data/controller/DataFileController.java | 8 + .../data/controller/MinioAdminController.java | 127 +++++++++++ .../com/sdm/data/model/req/FileSearchReq.java | 9 +- .../data/model/req/MinioCreatePolicyReq.java | 15 ++ .../data/model/req/MinioCreateUserReq.java | 23 ++ .../req/MinioCreateUserWithBucketReq.java | 18 ++ .../sdm/data/model/req/QueryBigFileReq.java | 12 +- .../sdm/data/service/IDataFileService.java | 9 + .../com/sdm/data/service/IMinioService.java | 65 +++++- .../service/impl/DataStorageAnalysisImpl.java | 3 +- .../data/service/impl/MinioAdminService.java | 201 ++++++++++++++++++ .../impl/MinioFileIDataFileServiceImpl.java | 75 +++++-- .../sdm/data/service/minio/MinioService.java | 158 +++++++++++--- data/src/main/resources/application-dev.yml | 11 +- data/src/main/resources/application-local.yml | 3 +- data/src/main/resources/application-prod.yml | 3 +- data/src/main/resources/application-test.yml | 3 +- 24 files changed, 723 insertions(+), 81 deletions(-) create mode 100644 data/src/main/java/com/sdm/data/controller/MinioAdminController.java create mode 100644 data/src/main/java/com/sdm/data/model/req/MinioCreatePolicyReq.java create mode 100644 data/src/main/java/com/sdm/data/model/req/MinioCreateUserReq.java create mode 100644 data/src/main/java/com/sdm/data/model/req/MinioCreateUserWithBucketReq.java create mode 100644 data/src/main/java/com/sdm/data/service/impl/MinioAdminService.java diff --git a/.idea/compiler.xml b/.idea/compiler.xml index cdf7dc2c..126dfa14 100644 --- a/.idea/compiler.xml +++ b/.idea/compiler.xml @@ -15,6 +15,7 @@ + @@ -33,6 +34,7 @@ + diff --git a/.idea/encodings.xml b/.idea/encodings.xml index 1495f1a6..246703ed 100644 --- a/.idea/encodings.xml +++ b/.idea/encodings.xml @@ -12,6 +12,7 @@ + diff --git a/common/src/main/java/com/sdm/common/entity/enums/DirTypeEnum.java b/common/src/main/java/com/sdm/common/entity/enums/DirTypeEnum.java index 408dbb1b..6a262d7d 100644 --- a/common/src/main/java/com/sdm/common/entity/enums/DirTypeEnum.java +++ b/common/src/main/java/com/sdm/common/entity/enums/DirTypeEnum.java @@ -32,7 +32,12 @@ public enum DirTypeEnum { * 训练模型文件夹 */ @Schema(description = "训练模型文件", example = "5") - TRAIN_MODEL_DIR("trainModel", 5); + TRAIN_MODEL_DIR("trainModel", 5), + + @Schema(description = "脚本文件夹", example = "6") + SCRIPT_DIR("script", 6); + + String dirName; int value; diff --git a/common/src/main/java/com/sdm/common/entity/enums/FileBizTypeEnum.java b/common/src/main/java/com/sdm/common/entity/enums/FileBizTypeEnum.java index 39da2f07..c388f19f 100644 --- a/common/src/main/java/com/sdm/common/entity/enums/FileBizTypeEnum.java +++ b/common/src/main/java/com/sdm/common/entity/enums/FileBizTypeEnum.java @@ -3,7 +3,6 @@ package com.sdm.common.entity.enums; import io.swagger.v3.oas.annotations.media.Schema; @Schema(description = "文件业务类型枚举") - public enum FileBizTypeEnum { /** * 模型文件 diff --git a/common/src/main/java/com/sdm/common/feign/inter/data/IDataFeignClient.java b/common/src/main/java/com/sdm/common/feign/inter/data/IDataFeignClient.java index 3c259c67..88ad7b02 100644 --- a/common/src/main/java/com/sdm/common/feign/inter/data/IDataFeignClient.java +++ b/common/src/main/java/com/sdm/common/feign/inter/data/IDataFeignClient.java @@ -6,12 +6,14 @@ import com.sdm.common.entity.req.data.DelDirReq; import com.sdm.common.entity.req.data.RenameDirReq; import com.sdm.common.entity.req.system.LaunchApproveReq; import com.sdm.common.entity.resp.data.FileMetadataInfoResp; +import io.swagger.v3.oas.annotations.Operation; import org.springframework.cloud.openfeign.FeignClient; import org.springframework.validation.annotation.Validated; import org.springframework.web.bind.annotation.GetMapping; 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.multipart.MultipartFile; import java.util.List; @@ -24,11 +26,11 @@ public interface IDataFeignClient { SdmResponse createDir(@RequestBody @Validated CreateDirReq req); @PostMapping("/data/renameDirNew") - public SdmResponse renameDirNew(@RequestBody @Validated RenameDirReq req); + SdmResponse renameDirNew(@RequestBody @Validated RenameDirReq req); @PostMapping("/data/delDir") - public SdmResponse delDir(@RequestBody @Validated DelDirReq req); + SdmResponse delDir(@RequestBody @Validated DelDirReq req); @PostMapping("/data/approveDataFile") SdmResponse approveDataFile(@RequestBody LaunchApproveReq req); diff --git a/data/pom.xml b/data/pom.xml index 406b5c72..f6b20554 100644 --- a/data/pom.xml +++ b/data/pom.xml @@ -83,6 +83,13 @@ 8.5.7 + + io.minio + minio-admin + 8.5.7 + + + commons-io diff --git a/data/src/main/java/com/sdm/data/config/MinioConfig.java b/data/src/main/java/com/sdm/data/config/MinioConfig.java index 0cbbc09a..bee3a529 100644 --- a/data/src/main/java/com/sdm/data/config/MinioConfig.java +++ b/data/src/main/java/com/sdm/data/config/MinioConfig.java @@ -1,31 +1,40 @@ package com.sdm.data.config; import io.minio.MinioClient; -import org.springframework.beans.factory.annotation.Value; +import io.minio.admin.MinioAdminClient; +import lombok.Data; +import org.springframework.boot.context.properties.ConfigurationProperties; +import org.springframework.boot.context.properties.EnableConfigurationProperties; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; @Configuration +@ConfigurationProperties(prefix = "minio") +@Data public class MinioConfig { - - @Value("${minio.endpoint}") private String endpoint; - - @Value("${minio.port}") // API端口,默认9000 + // API端口,默认9000 private int port; - @Value("${minio.access-key}") private String accessKey; - @Value("${minio.secret-key}") private String secretKey; - @Value("${minio.bucket-name}") - private String bucketName; - - @Value("${minio.secure}") private boolean secure; + private String secretBusinessBucket; // 保密业务代码桶 + + private String spdmBucket; // 普通业务数据桶 + + // 初始化超级管理员客户端(用于 admin 操作:桶、用户、策略) + @Bean + public MinioAdminClient minioAdminClient() { + return MinioAdminClient.builder() + .endpoint(endpoint, port, secure) + .credentials(accessKey, secretKey) + .build(); + } + @Bean public MinioClient minioClient() { return MinioClient.builder() @@ -33,8 +42,4 @@ public class MinioConfig { .credentials(accessKey, secretKey) .build(); } - - public String getBucketName() { - return bucketName; - } -} +} \ No newline at end of file diff --git a/data/src/main/java/com/sdm/data/controller/DataFileController.java b/data/src/main/java/com/sdm/data/controller/DataFileController.java index c8d48682..9a4cba0f 100644 --- a/data/src/main/java/com/sdm/data/controller/DataFileController.java +++ b/data/src/main/java/com/sdm/data/controller/DataFileController.java @@ -351,6 +351,14 @@ public class DataFileController implements IDataFeignClient { return IDataFileService.uploadAvatar(avatar); } + @PostMapping(value = "/uploadScriptFile") + @Operation(summary = "上传脚本文件", description = "上传脚本文件") + public SdmResponse uploadScriptFile(@RequestParam("script") MultipartFile script) { + return IDataFileService.uploadScriptFile(script); + } + + + // 图片预览 @GetMapping("/previewImage") diff --git a/data/src/main/java/com/sdm/data/controller/MinioAdminController.java b/data/src/main/java/com/sdm/data/controller/MinioAdminController.java new file mode 100644 index 00000000..2d66f030 --- /dev/null +++ b/data/src/main/java/com/sdm/data/controller/MinioAdminController.java @@ -0,0 +1,127 @@ +package com.sdm.data.controller; + +import com.sdm.common.common.SdmResponse; +import com.sdm.data.model.req.MinioCreatePolicyReq; +import com.sdm.data.model.req.MinioCreateUserReq; +import com.sdm.data.model.req.MinioCreateUserWithBucketReq; +import com.sdm.data.service.impl.MinioAdminService; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.tags.Tag; +import lombok.extern.slf4j.Slf4j; +import org.bouncycastle.crypto.InvalidCipherTextException; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.*; + +import java.io.IOException; +import java.security.InvalidKeyException; +import java.security.NoSuchAlgorithmException; +import java.util.List; +import java.util.Map; + +@Slf4j +@RestController +@RequestMapping("/minioAdmin") +@Tag(name = "MinIO管理接口", description = "用于管理MinIO用户和策略的接口") +public class MinioAdminController { + + @Autowired + private MinioAdminService minioAdminService; + + @PostMapping("/createUserWithBucketFullAccess") + @Operation(summary = "创建MinIO用户并授予bucket访问权限", description = "创建一个新的MinIO用户并授予bucket访问权限") + public SdmResponse createUserWithBucketFullAccess(@RequestBody MinioCreateUserWithBucketReq req) { + try { + minioAdminService.createUserWithBucketFullAccess(req.getUsername(), req.getPassword(), req.getBucketName()); + return SdmResponse.success("创建MinIO用户并授予bucket访问权限成功"); + } catch (InvalidCipherTextException | NoSuchAlgorithmException | IOException | InvalidKeyException e) { + log.error("创建MinIO用户失败: username={}, bucketName={}", req.getUsername(), req.getBucketName(), e); + return SdmResponse.failed("创建用户失败: " + e.getMessage()); + } + } + + @PostMapping("/createUser") + @Operation(summary = "创建MinIO用户", description = "创建一个新的MinIO用户并可选地关联策略") + public SdmResponse createUser(@RequestBody MinioCreateUserReq req) { + try { + minioAdminService.createUser(req.getAccessKey(), req.getSecretKey(), req.getPolicyName(), req.getMemberOf()); + return SdmResponse.success("用户创建成功"); + } catch (Exception e) { + log.error("创建MinIO用户失败: accessKey={}", req.getAccessKey(), e); + return SdmResponse.failed("创建用户失败: " + e.getMessage()); + } + } + + @GetMapping("/deleteUser") + @Operation(summary = "删除MinIO用户", description = "根据用户名删除指定的MinIO用户") + public SdmResponse deleteUser(@RequestParam String accessKey) { + try { + minioAdminService.deleteUser(accessKey); + return SdmResponse.success("用户删除成功"); + } catch (Exception e) { + log.error("删除MinIO用户失败: accessKey={}", accessKey, e); + return SdmResponse.failed("删除用户失败: " + e.getMessage()); + } + } + + @PostMapping("/createPolicy") + @Operation(summary = "创建访问策略", description = "创建一个新的访问策略") + public SdmResponse createPolicy(@RequestBody MinioCreatePolicyReq req) { + try { + minioAdminService.createPolicy(req.getPolicyName(), req.getPolicyJson()); + return SdmResponse.success("策略创建成功"); + } catch (Exception e) { + log.error("创建MinIO策略失败: policyName={}", req.getPolicyName(), e); + return SdmResponse.failed("创建策略失败: " + e.getMessage()); + } + } + + @GetMapping("attachPolicyToUser") + @Operation(summary = "绑定策略到用户", description = "将指定的策略绑定到用户") + public SdmResponse attachPolicyToUser( + @RequestParam String username, + @RequestParam String policyName) { + try { + minioAdminService.attachPolicyToUser(username, policyName); + return SdmResponse.success("策略绑定成功"); + } catch (Exception e) { + log.error("绑定策略到用户失败: username={}, policyName={}", username, policyName, e); + return SdmResponse.failed("绑定策略失败: " + e.getMessage()); + } + } + + @GetMapping("/listAllUsers") + @Operation(summary = "列出所有用户", description = "获取所有MinIO用户的列表") + public SdmResponse listAllUsers() { + try { + List users = minioAdminService.listAllUsers(); + return SdmResponse.success(users); + } catch (Exception e) { + log.error("列出MinIO用户失败", e); + return SdmResponse.failed("获取用户列表失败: " + e.getMessage()); + } + } + + @GetMapping("/listAllPolicies") + @Operation(summary = "列出所有策略", description = "获取所有MinIO策略的列表") + public SdmResponse listAllPolicies() { + try { + Map policies = minioAdminService.listAllPolicies(); + return SdmResponse.success(policies); + } catch (Exception e) { + log.error("列出MinIO策略失败", e); + return SdmResponse.failed("获取策略列表失败: " + e.getMessage()); + } + } + + @GetMapping("/getUserPolicy") + @Operation(summary = "获取用户策略", description = "获取指定用户关联的策略") + public SdmResponse getUserPolicy(@RequestParam String username) { + try { + String policy = minioAdminService.getUserPolicy(username); + return SdmResponse.success(policy); + } catch (Exception e) { + log.error("获取用户策略失败: username={}", username, e); + return SdmResponse.failed("获取用户策略失败: " + e.getMessage()); + } + } +} \ No newline at end of file diff --git a/data/src/main/java/com/sdm/data/model/req/FileSearchReq.java b/data/src/main/java/com/sdm/data/model/req/FileSearchReq.java index e70cb971..9082e9c9 100644 --- a/data/src/main/java/com/sdm/data/model/req/FileSearchReq.java +++ b/data/src/main/java/com/sdm/data/model/req/FileSearchReq.java @@ -63,10 +63,13 @@ public class FileSearchReq extends BaseReq { private String fileSizeUnit; - @Schema(description = "文件创建时间") - private LocalDateTime createTime; + @Schema(description = "文件创建搜索开始时间") + private LocalDateTime startTime; - @Schema(description = "文件业务类型(1:模型文件 2:仿真报告、3:计算文件、4:曲线文件、5:云图文件,6:网格文件,7:计算过程文件)",implementation = FileBizTypeEnum.class) + @Schema(description = "文件创建搜索结束时间") + private LocalDateTime endTime; + + @Schema(description = "文件业务类型(1:模型文件 2:仿真报告、3:计算文件、4:曲线文件、5:云图文件,6:网格文件,7:计算过程文件)",enumAsRef = true) private Integer fileBizType; /** diff --git a/data/src/main/java/com/sdm/data/model/req/MinioCreatePolicyReq.java b/data/src/main/java/com/sdm/data/model/req/MinioCreatePolicyReq.java new file mode 100644 index 00000000..ea062fe4 --- /dev/null +++ b/data/src/main/java/com/sdm/data/model/req/MinioCreatePolicyReq.java @@ -0,0 +1,15 @@ +package com.sdm.data.model.req; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +@Data +@Schema(description = "创建MinIO策略请求参数") +public class MinioCreatePolicyReq { + + @Schema(description = "策略名称", requiredMode = Schema.RequiredMode.REQUIRED) + private String policyName; + + @Schema(description = "策略内容(JSON格式)", requiredMode = Schema.RequiredMode.REQUIRED) + private String policyJson; +} \ No newline at end of file diff --git a/data/src/main/java/com/sdm/data/model/req/MinioCreateUserReq.java b/data/src/main/java/com/sdm/data/model/req/MinioCreateUserReq.java new file mode 100644 index 00000000..53a2ff25 --- /dev/null +++ b/data/src/main/java/com/sdm/data/model/req/MinioCreateUserReq.java @@ -0,0 +1,23 @@ +package com.sdm.data.model.req; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +import java.util.List; + +@Data +@Schema(description = "创建MinIO用户请求参数") +public class MinioCreateUserReq { + + @Schema(description = "访问密钥(用户名)", requiredMode = Schema.RequiredMode.REQUIRED) + private String accessKey; + + @Schema(description = "私有密钥(密码)", requiredMode = Schema.RequiredMode.REQUIRED) + private String secretKey; + + @Schema(description = "策略名称") + private String policyName; + + @Schema(description = "所属用户组列表") + private List memberOf; +} \ No newline at end of file diff --git a/data/src/main/java/com/sdm/data/model/req/MinioCreateUserWithBucketReq.java b/data/src/main/java/com/sdm/data/model/req/MinioCreateUserWithBucketReq.java new file mode 100644 index 00000000..ba27d1ca --- /dev/null +++ b/data/src/main/java/com/sdm/data/model/req/MinioCreateUserWithBucketReq.java @@ -0,0 +1,18 @@ +package com.sdm.data.model.req; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +@Data +@Schema(description = "创建MinIO用户并授予bucket访问权限请求参数") +public class MinioCreateUserWithBucketReq { + + @Schema(description = "用户名", requiredMode = Schema.RequiredMode.REQUIRED) + private String username; + + @Schema(description = "密码", requiredMode = Schema.RequiredMode.REQUIRED) + private String password; + + @Schema(description = "桶名称", requiredMode = Schema.RequiredMode.REQUIRED) + private String bucketName; +} \ No newline at end of file diff --git a/data/src/main/java/com/sdm/data/model/req/QueryBigFileReq.java b/data/src/main/java/com/sdm/data/model/req/QueryBigFileReq.java index 2cc62fd1..deaac79b 100644 --- a/data/src/main/java/com/sdm/data/model/req/QueryBigFileReq.java +++ b/data/src/main/java/com/sdm/data/model/req/QueryBigFileReq.java @@ -19,10 +19,16 @@ public class QueryBigFileReq extends BaseReq{ private String fileName; /** - * 文件创建时间 createTime + * 文件创建时间 startTime */ - @Schema(description = "文件创建时间") - private LocalDateTime createTime; + @Schema(description = "文件创建搜索开始时间") + private LocalDateTime startTime; + + /** + * 文件创建时间 endTime + */ + @Schema(description = "文件创建搜索结束时间") + private LocalDateTime endTime; /** * 文件大小 diff --git a/data/src/main/java/com/sdm/data/service/IDataFileService.java b/data/src/main/java/com/sdm/data/service/IDataFileService.java index 1cd88c91..9db9dfa3 100644 --- a/data/src/main/java/com/sdm/data/service/IDataFileService.java +++ b/data/src/main/java/com/sdm/data/service/IDataFileService.java @@ -200,6 +200,15 @@ public interface IDataFileService { return null; } + /** + * 上传脚本文件 + * @param scriptFile 脚本 + * @return 上传文件id + */ + default SdmResponse uploadScriptFile(MultipartFile scriptFile){ + return null; + } + /** * 图片预览 * diff --git a/data/src/main/java/com/sdm/data/service/IMinioService.java b/data/src/main/java/com/sdm/data/service/IMinioService.java index b63016db..0690e04d 100644 --- a/data/src/main/java/com/sdm/data/service/IMinioService.java +++ b/data/src/main/java/com/sdm/data/service/IMinioService.java @@ -13,6 +13,13 @@ public interface IMinioService { * @return 存储桶名称 */ public String getBucketName(); + + /** + * 获取MinIO的保密业务存储桶名称 + * + * @return 保密业务存储桶名称 + */ + public String getSecretBusinessBucketName(); /** * 创建目录 @@ -20,6 +27,14 @@ public interface IMinioService { * @param objectKey 绝对路径目录名 */ public void createDirectoryByObjectKey(String objectKey); + + /** + * 创建目录 + * + * @param objectKey 绝对路径目录名 + * @param bucketName 桶名称 + */ + public void createDirectoryByObjectKey(String objectKey, String bucketName); /** * 递归删除指定目录下的所有对象。 @@ -27,12 +42,27 @@ public interface IMinioService { * @param directoryName 目录名称(objectKey) */ public void deleteDirectoryRecursively(String directoryName); + + /** + * 递归删除指定目录下的所有对象。 + * + * @param directoryName 目录名称(objectKey) + * @param bucketName 桶名称 + */ + public void deleteDirectoryRecursively(String directoryName, String bucketName); /** * 从MinIO删除文件 * @param minioObjectKey 文件名(objectKey) */ public void deleteFile(String minioObjectKey); + + /** + * 从MinIO删除文件 + * @param minioObjectKey 文件名(objectKey) + * @param bucketName 桶名称 + */ + public void deleteFile(String minioObjectKey, String bucketName); /** * 上传文件到MinIO @@ -41,6 +71,15 @@ public interface IMinioService { * @param tags 文件标签 */ public void uploadFile(MultipartFile file, String objectName, Map tags); + + /** + * 上传文件到MinIO + * @param file 文件对象 + * @param objectName 文件名(objectKey) + * @param tags 文件标签 + * @param bucketName 桶名称 + */ + public void uploadFile(MultipartFile file, String objectName, Map tags, String bucketName); /** * 重命名MinIO中的文件 @@ -50,6 +89,16 @@ public interface IMinioService { * @throws Exception 异常信息 */ public void renameFile(String oldObjectName, String newObjectName); + + /** + * 重命名MinIO中的文件 + * + * @param oldObjectName 原文件名(objectKey) + * @param newObjectName 新文件名(objectKey) + * @param bucketName 桶名称 + * @throws Exception 异常信息 + */ + public void renameFile(String oldObjectName, String newObjectName, String bucketName); /** @@ -57,14 +106,28 @@ public interface IMinioService { * @param objectName 文件名(objectKey) */ byte[] downloadFile(String objectName) throws Exception; + + /** + * 从MinIO下载文件 + * @param objectName 文件名(objectKey) + * @param bucketName 桶名称 + */ + byte[] downloadFile(String objectName, String bucketName) throws Exception; InputStream getMinioInputStream(String objectName); + InputStream getMinioInputStream(String objectName, String bucketName); /** * 根据标签查询文件 */ List queryFilesByTags(Map tags) throws Exception; + + /** + * 根据标签查询文件 + */ + List queryFilesByTags(Map tags, String bucketName) throws Exception; String getMinioPresignedUrl(String objectKey); + String getMinioPresignedUrl(String objectKey, String bucketName); -} +} \ No newline at end of file diff --git a/data/src/main/java/com/sdm/data/service/impl/DataStorageAnalysisImpl.java b/data/src/main/java/com/sdm/data/service/impl/DataStorageAnalysisImpl.java index 33efd8a1..a2e16430 100644 --- a/data/src/main/java/com/sdm/data/service/impl/DataStorageAnalysisImpl.java +++ b/data/src/main/java/com/sdm/data/service/impl/DataStorageAnalysisImpl.java @@ -179,7 +179,8 @@ public class DataStorageAnalysisImpl implements DataStorageAnalysis { .eq(ObjectUtils.isNotEmpty(queryBigFileReq.getFileSuffix()), FileStorage::getFileSuffix, queryBigFileReq.getFileSuffix()) .eq(ObjectUtils.isNotEmpty(queryBigFileReq.getFileBizType()), FileStorage::getFileBizType, queryBigFileReq.getFileBizType()) .like(ObjectUtils.isNotEmpty(queryBigFileReq.getFileName()), FileStorage::getFileName, queryBigFileReq.getFileName()) - .gt(ObjectUtils.isNotEmpty(queryBigFileReq.getCreateTime()), FileStorage::getCreateTime, queryBigFileReq.getCreateTime()) + .gt(ObjectUtils.isNotEmpty(queryBigFileReq.getStartTime()), FileStorage::getCreateTime, queryBigFileReq.getStartTime()) + .lt(ObjectUtils.isNotEmpty(queryBigFileReq.getEndTime()), FileStorage::getCreateTime, queryBigFileReq.getEndTime()) .gt(ObjectUtils.isNotEmpty(fileSizeInBytes), FileStorage::getFileSize, fileSizeInBytes).list(); PageInfo page = new PageInfo<>(list); return PageUtils.getJsonObjectSdmResponse(list, page); diff --git a/data/src/main/java/com/sdm/data/service/impl/MinioAdminService.java b/data/src/main/java/com/sdm/data/service/impl/MinioAdminService.java new file mode 100644 index 00000000..c6ffb545 --- /dev/null +++ b/data/src/main/java/com/sdm/data/service/impl/MinioAdminService.java @@ -0,0 +1,201 @@ +package com.sdm.data.service.impl; + +import com.sdm.data.config.MinioConfig; +import io.minio.admin.MinioAdminClient; +import io.minio.admin.UserInfo; +import org.bouncycastle.crypto.InvalidCipherTextException; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + +import java.io.IOException; +import java.security.InvalidKeyException; +import java.security.NoSuchAlgorithmException; +import java.util.ArrayList; +import java.util.List; +import java.util.Map; +import java.util.Set; + +@Service +public class MinioAdminService { + @Autowired + private MinioAdminClient minioAdminClient; + + @Autowired + private MinioConfig minioConfig; + + /** + * 创建MinIO用户 + * + * @param accessKey 用户名(AccessKey) + * @param secretKey 密码(SecretKey) + * @param policyName 关联的策略名称(可为null) + * @param memberOf 所属用户组列表(可为null) + */ + public void createUser(String accessKey, String secretKey, String policyName, List memberOf) throws InvalidCipherTextException, NoSuchAlgorithmException, IOException, InvalidKeyException { + // 用户状态设置为启用 + minioAdminClient.addUser(accessKey, UserInfo.Status.ENABLED, secretKey, policyName, memberOf); + } + + /** + * 创建用户并为其分配指定桶的完全访问权限 + * + * @param username 用户名 + * @param password 密码 + * @param bucketName 桶名称 + * @throws InvalidCipherTextException 无效加密文本异常 + * @throws NoSuchAlgorithmException 无此算法异常 + * @throws IOException IO异常 + * @throws InvalidKeyException 无效密钥异常 + */ + public void createUserWithBucketFullAccess(String username, String password, String bucketName) + throws InvalidCipherTextException, NoSuchAlgorithmException, IOException, InvalidKeyException { + // 生成策略名称 + String policyName = bucketName + "-full-access-policy"; + + // 创建针对指定桶的完全访问策略 + createBucketFullAccessPolicy(policyName, bucketName); + + // 创建用户 + createUser(username, password, null,null); + + // 绑定策略到用户 + attachPolicyToUser(username, policyName); + } + + /** + * 删除MinIO用户 + * + * @param accessKey 用户名(AccessKey) + * @throws NoSuchAlgorithmException 无此算法异常 + * @throws InvalidKeyException 无效密钥异常 + * @throws IOException IO异常 + */ + public void deleteUser(String accessKey) throws NoSuchAlgorithmException, InvalidKeyException, IOException { + minioAdminClient.deleteUser(accessKey); + } + + /** + * 创建MinIO访问策略 + * + * @param policyName 策略名称 + * @param policyJson 策略JSON字符串 + * @throws NoSuchAlgorithmException 无此算法异常 + * @throws InvalidKeyException 无效密钥异常 + * @throws IOException IO异常 + */ + public void createPolicy(String policyName, String policyJson) + throws NoSuchAlgorithmException, InvalidKeyException, IOException { + minioAdminClient.addCannedPolicy(policyName, policyJson); + } + + + /** + * 创建针对指定桶的完全访问策略 + * + * @param policyName 策略名称 + * @param bucketName 桶名称 + * @throws NoSuchAlgorithmException 无此算法异常 + * @throws InvalidKeyException 无效密钥异常 + * @throws IOException IO异常 + */ + public void createBucketFullAccessPolicy(String policyName, String bucketName) + throws NoSuchAlgorithmException, InvalidKeyException, IOException { + String policyJson = "{\n" + + " \"Version\": \"2012-10-17\",\n" + + " \"Statement\": [\n" + + " {\n" + + " \"Effect\": \"Allow\",\n" + + " \"Action\": \"s3:*\",\n" + + " \"Resource\": [\n" + + " \"arn:aws:s3:::" + bucketName + "\",\n" + + " \"arn:aws:s3:::" + bucketName + "/*\"\n" + + " ]\n" + + " }\n" + + " ]\n" + + "}"; + + createPolicy(policyName, policyJson); + } + + /** + * 将策略绑定到用户 + * + * @param username 用户名 + * @param policyName 策略名称 + * @throws NoSuchAlgorithmException 无此算法异常 + * @throws InvalidKeyException 无效密钥异常 + * @throws IOException IO异常 + */ + public void attachPolicyToUser(String username, String policyName) + throws NoSuchAlgorithmException, InvalidKeyException, IOException { + // 第二个参数false表示操作对象是用户而非用户组 + minioAdminClient.setPolicy(username, false, policyName); + } + + /** + * 列出所有MinIO用户 + * + * @return 用户列表(AccessKey集合) + * @throws NoSuchAlgorithmException 无此算法异常 + * @throws InvalidKeyException 无效密钥异常 + * @throws IOException IO异常 + * @throws InvalidCipherTextException 无效加密文本异常 + */ + public List listAllUsers() + throws NoSuchAlgorithmException, InvalidKeyException, IOException, InvalidCipherTextException { + Map userMap = minioAdminClient.listUsers(); + return new ArrayList<>(userMap.keySet()); + } + + /** + * 列出所有MinIO访问策略 + * + * @return 策略名称列表 + * @throws NoSuchAlgorithmException 无此算法异常 + * @throws InvalidKeyException 无效密钥异常 + * @throws IOException IO异常 + */ + public Map listAllPolicies() throws NoSuchAlgorithmException, InvalidKeyException, IOException { + Map policyNames = minioAdminClient.listCannedPolicies(); + return policyNames; + } + + /** + * 查询用户关联的策略 + * + * @param username 用户名(AccessKey) + * @return 策略名称(无关联策略时返回null) + * @throws NoSuchAlgorithmException 无此算法异常 + * @throws InvalidKeyException 无效密钥异常 + * @throws IOException IO异常 + * @throws InvalidCipherTextException 无效加密文本异常 + */ + public String getUserPolicy(String username) + throws NoSuchAlgorithmException, InvalidKeyException, IOException, InvalidCipherTextException { + Map userMap = minioAdminClient.listUsers(); + UserInfo userInfo = userMap.get(username); + if (userInfo != null) { + return userInfo.policyName(); + } + return null; + } + + /** + * 根据策略名称查询具体策略内容 + * + * @param policyName 策略名称 + * @return 策略的JSON字符串内容,若策略不存在则返回null + * @throws NoSuchAlgorithmException 无此算法异常 + * @throws InvalidKeyException 无效密钥异常 + * @throws IOException IO异常 + */ + public String getPolicyByPolicyName(String policyName) + throws NoSuchAlgorithmException, InvalidKeyException, IOException { + // 先检查策略是否存在 + if (minioAdminClient.listCannedPolicies().containsKey(policyName)) { + // 获取并返回策略的JSON内容 + return minioAdminClient.listCannedPolicies().get(policyName); + } + return null; + } +} \ No newline at end of file diff --git a/data/src/main/java/com/sdm/data/service/impl/MinioFileIDataFileServiceImpl.java b/data/src/main/java/com/sdm/data/service/impl/MinioFileIDataFileServiceImpl.java index 65cb644d..fc51560d 100644 --- a/data/src/main/java/com/sdm/data/service/impl/MinioFileIDataFileServiceImpl.java +++ b/data/src/main/java/com/sdm/data/service/impl/MinioFileIDataFileServiceImpl.java @@ -65,9 +65,11 @@ import java.util.stream.Collectors; @Slf4j @Service public class MinioFileIDataFileServiceImpl implements IDataFileService { - private static final List INIT_DIR = List.of( + // 初始化用户业务库目录 + private static final List INIT_SPMD_DIR = List.of( DirTypeEnum.KNOWLEDGE_BASE_DIR, DirTypeEnum.PROJECT_NODE_DIR, - DirTypeEnum.AVATAR_DIR, DirTypeEnum.SIMULATION_PARAMETER_DIR, DirTypeEnum.TRAIN_MODEL_DIR); + DirTypeEnum.AVATAR_DIR, DirTypeEnum.SIMULATION_PARAMETER_DIR, DirTypeEnum.TRAIN_MODEL_DIR,DirTypeEnum.SCRIPT_DIR); + // fileData 知识库文件列表可见的数据 private final List fileDatdList = Arrays.asList( NumberConstants.ZERO, @@ -599,8 +601,9 @@ public class MinioFileIDataFileServiceImpl implements IDataFileService { @Override public SdmResponse fileSearch(FileSearchReq minioFileSearchReq) { - FileMetadataInfo fileMetadataInfo = null; + QueryBigFileReq queryBigFileReq = new QueryBigFileReq(); + FileMetadataInfo fileMetadataInfo = null; if (ObjectUtils.isNotEmpty(minioFileSearchReq.getParentUuid())) { // 项目节点下搜索文件 fileMetadataInfo = fileMetadataInfoService.lambdaQuery().eq(FileMetadataInfo::getRelatedResourceUuid, minioFileSearchReq.getParentUuid()).one(); @@ -609,13 +612,12 @@ public class MinioFileIDataFileServiceImpl implements IDataFileService { fileMetadataInfo = fileMetadataInfoService.getById(minioFileSearchReq.getParentDirId()); } - if (ObjectUtils.isEmpty(fileMetadataInfo)) { - return SdmResponse.success(); + if (ObjectUtils.isNotEmpty(fileMetadataInfo)) { + queryBigFileReq.setDirId(fileMetadataInfo.getId()); } - QueryBigFileReq queryBigFileReq = new QueryBigFileReq(); BeanUtils.copyProperties(minioFileSearchReq, queryBigFileReq); - queryBigFileReq.setDirId(fileMetadataInfo.getId()); + SdmResponse>> searchResult = dataStorageAnalysis.listBigFile(queryBigFileReq); PageDataResp> pageDataResp = searchResult.getData(); List data = pageDataResp.getData(); @@ -812,7 +814,7 @@ public class MinioFileIDataFileServiceImpl implements IDataFileService { @Override @Transactional(rollbackFor = Exception.class) public boolean initSystemDirectory(String company) { - for (DirTypeEnum dirType : INIT_DIR) { + for (DirTypeEnum dirType : INIT_SPMD_DIR) { String dirMinioObjectKey = getDirMinioObjectKey(dirType.getDirName()); try { // 检查目录是否已存在 @@ -1451,20 +1453,65 @@ public class MinioFileIDataFileServiceImpl implements IDataFileService { String newFilename = filenameWithoutSuffix + "_" + timestamp + "." + suffix; // 再上传训练模型文件 - String simulationParamMinioObjectKey = getFileMinioObjectKey(trainModelDirMetadataInfo.getObjectKey() + newFilename); + String trainingMinioObjectKey = getFileMinioObjectKey(trainModelDirMetadataInfo.getObjectKey() + newFilename); try { - minioService.uploadFile(trainModelFile, simulationParamMinioObjectKey, null); + minioService.uploadFile(trainModelFile, trainingMinioObjectKey, null); // 创建目录元数据并保存到数据库 - FileMetadataInfo fileInfo = createFileMetadata(simulationParamMinioObjectKey, originalFilename, null, + FileMetadataInfo fileInfo = createFileMetadata(trainingMinioObjectKey, originalFilename, null, null, null, null, parTrainModelDirId, trainModelFile.getSize()); fileMetadataInfoService.save(fileInfo); return SdmResponse.success(fileInfo.getId()); } catch (Exception e) { - minioService.deleteFile(simulationParamMinioObjectKey); - log.error("上传仿真参数文件", e); - throw new RuntimeException("上传仿真参数文件: " + e.getMessage(), e); + minioService.deleteFile(trainingMinioObjectKey); + log.error("上传训练模型文件失败", e); + throw new RuntimeException("上传训练模型文件失败: " + e.getMessage(), e); + } + } + + @Override + public SdmResponse uploadScriptFile(MultipartFile scriptFile) { + // 先创建 script 目录 + String dirMinioObjectKey = getDirMinioObjectKey(DirTypeEnum.SCRIPT_DIR.getDirName()); + Optional fileMetadataInfoByObjectKey = getFileMetadataInfoByObjectKey(dirMinioObjectKey); + // 检查目录是否已存在 + if (!fileMetadataInfoByObjectKey.isPresent()) { + return SdmResponse.failed("script 目录不存在,等待initSystemDirectory 初始化完成"); + } + + // 检查文件是否为空 + if (scriptFile == null || scriptFile.isEmpty()) { + return SdmResponse.failed("请选择要上传的仿真参数库文件"); + } + + // 获取 script 目录的 id + FileMetadataInfo scriptDirMetadataInfo = fileMetadataInfoByObjectKey.get(); + Long parScriptDirId = scriptDirMetadataInfo.getId(); + + String originalFilename = scriptFile.getOriginalFilename(); + String suffix = originalFilename.substring(originalFilename.lastIndexOf(".") + 1); + + // 生成带时间戳的文件名以避免冲突 + String filenameWithoutSuffix = originalFilename.substring(0, originalFilename.lastIndexOf(".")); + String timestamp = String.valueOf(System.currentTimeMillis()); + String newFilename = filenameWithoutSuffix + "_" + timestamp + "." + suffix; + + // 再上传脚本文件 + String scriptFileMinioObjectKey = getFileMinioObjectKey(scriptDirMetadataInfo.getObjectKey() + newFilename); + + try { + minioService.uploadFile(scriptFile, scriptFileMinioObjectKey, null); + + // 创建目录元数据并保存到数据库 + FileMetadataInfo fileInfo = createFileMetadata(scriptFileMinioObjectKey, originalFilename, null, + null, null, null, parScriptDirId, scriptFile.getSize()); + fileMetadataInfoService.save(fileInfo); + return SdmResponse.success(fileInfo.getId()); + } catch (Exception e) { + minioService.deleteFile(scriptFileMinioObjectKey); + log.error("上传传脚本文件", e); + throw new RuntimeException("上传传脚本文件: " + e.getMessage(), e); } } diff --git a/data/src/main/java/com/sdm/data/service/minio/MinioService.java b/data/src/main/java/com/sdm/data/service/minio/MinioService.java index 00e77d52..11933332 100644 --- a/data/src/main/java/com/sdm/data/service/minio/MinioService.java +++ b/data/src/main/java/com/sdm/data/service/minio/MinioService.java @@ -1,6 +1,5 @@ package com.sdm.data.service.minio; - import com.sdm.data.config.MinioConfig; import com.sdm.data.service.IMinioService; import io.minio.*; @@ -16,6 +15,7 @@ import org.springframework.stereotype.Service; import org.springframework.util.StringUtils; import org.springframework.web.multipart.MultipartFile; +import javax.annotation.PostConstruct; import java.io.ByteArrayInputStream; import java.io.IOException; import java.io.InputStream; @@ -39,16 +39,41 @@ public class MinioService implements IMinioService { this.minioConfig = minioConfig; } + /** + * 在应用启动时初始化桶 + */ + @PostConstruct + public void initializeBucket() { + try { + createBucketIfNotExists(minioConfig.getSpdmBucket()); + log.info("桶{}初始化完成", minioConfig.getSpdmBucket()); + } catch (Exception e) { + log.error("桶{}初始化失败", minioConfig.getSpdmBucket(), e); + } + + try { + createBucketIfNotExists(minioConfig.getSecretBusinessBucket()); + log.info("桶{}初始化完成", minioConfig.getSecretBusinessBucket()); + } catch (Exception e) { + log.error("桶{}初始化失败", minioConfig.getSecretBusinessBucket(), e); + } + } + public String getBucketName() { - return minioConfig.getBucketName(); + return minioConfig.getSpdmBucket(); + } + + public String getSecretBusinessBucketName() { + return minioConfig.getSecretBusinessBucket(); } /** * 创建目录 * * @param objectKey 绝对路径目录名 + * @param bucketName 桶名称 */ - public void createDirectoryByObjectKey(String objectKey) { + public void createDirectoryByObjectKey(String objectKey, String bucketName) { try { // 确保目录名以 "/" 结尾 @@ -57,7 +82,7 @@ public class MinioService implements IMinioService { // 使用空内容创建目录对象 ObjectWriteResponse objectWriteResponse = minioClient.putObject( PutObjectArgs.builder() - .bucket(minioConfig.getBucketName()) + .bucket(bucketName) .object(objectKey) .stream(new ByteArrayInputStream(new byte[0]), 0, -1) .build()); @@ -65,6 +90,15 @@ public class MinioService implements IMinioService { throw new RuntimeException(e); } } + + /** + * 创建目录(默认使用spdmBucket) + * + * @param objectKey 绝对路径目录名 + */ + public void createDirectoryByObjectKey(String objectKey) { + createDirectoryByObjectKey(objectKey, minioConfig.getSpdmBucket()); + } private static String dealDirPath(String dirPath) { if (dirPath.startsWith("/")) { @@ -81,8 +115,9 @@ public class MinioService implements IMinioService { * 递归删除指定目录下的所有对象。 * * @param directoryName 目录名称 + * @param bucketName 桶名称 */ - public void deleteDirectoryRecursively(String directoryName) { + public void deleteDirectoryRecursively(String directoryName, String bucketName) { try { // 确保目录名以 "/" 结尾 @@ -91,7 +126,7 @@ public class MinioService implements IMinioService { // 列出目录下的所有对象 Iterable> results = minioClient.listObjects( ListObjectsArgs.builder() - .bucket(minioConfig.getBucketName()) + .bucket(bucketName) .prefix(directoryName) .recursive(true) .build()); @@ -111,7 +146,7 @@ public class MinioService implements IMinioService { Iterable> deleteErrors = minioClient.removeObjects( RemoveObjectsArgs.builder() - .bucket(minioConfig.getBucketName()) + .bucket(bucketName) .objects(deleteObjects) .build()); @@ -126,17 +161,28 @@ public class MinioService implements IMinioService { throw new RuntimeException(e); } } + + /** + * 递归删除指定目录下的所有对象(默认使用spdmBucket)。 + * + * @param directoryName 目录名称 + */ + public void deleteDirectoryRecursively(String directoryName) { + deleteDirectoryRecursively(directoryName, minioConfig.getSpdmBucket()); + } /** * 从MinIO删除文件 + * @param minioObjectKey 文件名 + * @param bucketName 桶名称 */ - public void deleteFile(String minioObjectKey) { + public void deleteFile(String minioObjectKey, String bucketName) { try { // 确保目录名以 "/" 结尾 minioObjectKey = dealDirPath(minioObjectKey); minioClient.removeObject( RemoveObjectArgs.builder() - .bucket(minioConfig.getBucketName()) + .bucket(bucketName) .object(minioObjectKey) .build()); } catch (Exception e) { @@ -145,12 +191,23 @@ public class MinioService implements IMinioService { } /** - * 上传文件到MinIO + * 从MinIO删除文件(默认使用spdmBucket) */ - public void uploadFile(MultipartFile file, String objectName, Map tags) { + public void deleteFile(String minioObjectKey) { + deleteFile(minioObjectKey, minioConfig.getSpdmBucket()); + } + + /** + * 上传文件到MinIO + * @param file 文件对象 + * @param objectName 文件名 + * @param tags 文件标签 + * @param bucketName 桶名称 + */ + public void uploadFile(MultipartFile file, String objectName, Map tags, String bucketName) { try { - // 检查存储桶是否存在,不存在则创建 - createBucketIfNotExists(); + // 检查存储桶是否存在,不存在则创建(为了向后兼容,仍然保留此处检查) + createBucketIfNotExists(bucketName); // 转换标签为MinIO格式 Map tagMap = tags != null ? tags : Map.of(); @@ -159,7 +216,7 @@ public class MinioService implements IMinioService { try (InputStream inputStream = file.getInputStream()) { minioClient.putObject( PutObjectArgs.builder() - .bucket(minioConfig.getBucketName()) + .bucket(bucketName) .object(objectName) .stream(inputStream, file.getSize(), -1) .contentType(file.getContentType()) @@ -172,14 +229,22 @@ public class MinioService implements IMinioService { } } + /** + * 上传文件到MinIO(默认使用spdmBucket) + */ + public void uploadFile(MultipartFile file, String objectName, Map tags) { + uploadFile(file, objectName, tags, minioConfig.getSpdmBucket()); + } + /** * 重命名MinIO中的文件 * * @param oldObjectName 原文件名 * @param newObjectName 新文件名 + * @param bucketName 桶名称 * @throws Exception 异常信息 */ - public void renameFile(String oldObjectName, String newObjectName) { + public void renameFile(String oldObjectName, String newObjectName, String bucketName) { try { // 参数校验 if (!StringUtils.hasText(oldObjectName)) { @@ -193,7 +258,7 @@ public class MinioService implements IMinioService { // 检查原文件是否存在 StatObjectResponse stat = minioClient.statObject( StatObjectArgs.builder() - .bucket(minioConfig.getBucketName()) + .bucket(bucketName) .object(oldObjectName) .build()); @@ -201,10 +266,10 @@ public class MinioService implements IMinioService { // 复制文件到新名称 minioClient.copyObject( CopyObjectArgs.builder() - .bucket(minioConfig.getBucketName()) + .bucket(bucketName) .object(newObjectName) .source(CopySource.builder() - .bucket(minioConfig.getBucketName()) + .bucket(bucketName) .object(oldObjectName) .build()) .build()); @@ -212,7 +277,7 @@ public class MinioService implements IMinioService { // 删除原文件 minioClient.removeObject( RemoveObjectArgs.builder() - .bucket(minioConfig.getBucketName()) + .bucket(bucketName) .object(oldObjectName) .build()); } catch (Exception e) { @@ -220,28 +285,52 @@ public class MinioService implements IMinioService { throw new RuntimeException(e); } } + + /** + * 重命名MinIO中的文件(默认使用spdmBucket) + * + * @param oldObjectName 原文件名 + * @param newObjectName 新文件名 + * @throws Exception 异常信息 + */ + public void renameFile(String oldObjectName, String newObjectName) { + renameFile(oldObjectName, newObjectName, minioConfig.getSpdmBucket()); + } /** * 从MinIO下载文件 + * @param objectName 对象名称 + * @param bucketName 桶名称 */ - public byte[] downloadFile(String objectName) throws Exception { + public byte[] downloadFile(String objectName, String bucketName) throws Exception { try (InputStream stream = minioClient.getObject( GetObjectArgs.builder() - .bucket(minioConfig.getBucketName()) + .bucket(bucketName) .object(objectName) .build())) { return IOUtils.toByteArray(stream); } } + /** + * 从MinIO下载文件(默认使用spdmBucket) + */ + public byte[] downloadFile(String objectName) throws Exception { + return downloadFile(objectName, minioConfig.getSpdmBucket()); + } + @Override public InputStream getMinioInputStream(String objectName) { + return getMinioInputStream(objectName, minioConfig.getSpdmBucket()); + } + + public InputStream getMinioInputStream(String objectName, String bucketName) { try { return minioClient.getObject( GetObjectArgs.builder() - .bucket(minioConfig.getBucketName()) + .bucket(bucketName) .object(objectName) .build()); } catch (Exception e) { @@ -251,13 +340,15 @@ public class MinioService implements IMinioService { /** * 根据标签查询文件 + * @param tags 标签 + * @param bucketName 桶名称 */ - public List queryFilesByTags(Map tags) throws Exception { + public List queryFilesByTags(Map tags, String bucketName) throws Exception { List result = new ArrayList<>(); Iterable> results = minioClient.listObjects( ListObjectsArgs.builder() - .bucket(minioConfig.getBucketName()) + .bucket(bucketName) .build()); for (Result itemResult : results) { @@ -268,6 +359,13 @@ public class MinioService implements IMinioService { } return result; } + + /** + * 根据标签查询文件(默认使用spdmBucket) + */ + public List queryFilesByTags(Map tags) throws Exception { + return queryFilesByTags(tags, minioConfig.getSpdmBucket()); + } /** * 检查文件标签是否匹配查询条件 @@ -293,27 +391,31 @@ public class MinioService implements IMinioService { /** * 检查存储桶是否存在,不存在则创建 */ - private void createBucketIfNotExists() throws ServerException, InsufficientDataException, + private void createBucketIfNotExists(String bucketName) throws ServerException, InsufficientDataException, ErrorResponseException, IOException, NoSuchAlgorithmException, InvalidKeyException, InvalidResponseException, XmlParserException, InternalException { boolean found = minioClient.bucketExists(BucketExistsArgs.builder() - .bucket(minioConfig.getBucketName()) + .bucket(bucketName) .build()); if (!found) { minioClient.makeBucket(MakeBucketArgs.builder() - .bucket(minioConfig.getBucketName()) + .bucket(bucketName) .build()); } } @Override public String getMinioPresignedUrl(String objectKey) { + return getMinioPresignedUrl(objectKey, minioConfig.getSpdmBucket()); + } + + public String getMinioPresignedUrl(String objectKey, String bucketName) { String presignedUrl = null; try { // 生成预签名URL - GetPresignedObjectUrlArgs args = GetPresignedObjectUrlArgs.builder().method(Method.GET).bucket(minioConfig.getBucketName()).object(objectKey).expiry(3600, TimeUnit.SECONDS).build(); + GetPresignedObjectUrlArgs args = GetPresignedObjectUrlArgs.builder().method(Method.GET).bucket(bucketName).object(objectKey).expiry(3600, TimeUnit.SECONDS).build(); presignedUrl = minioClient.getPresignedObjectUrl(args); } catch (Exception e) { log.error("获取文件预览URL失败: " + objectKey, e); diff --git a/data/src/main/resources/application-dev.yml b/data/src/main/resources/application-dev.yml index 73ba7815..b0664055 100644 --- a/data/src/main/resources/application-dev.yml +++ b/data/src/main/resources/application-dev.yml @@ -100,17 +100,12 @@ fileSystem: system: system chose: minio # 这里选择minio或者system -#地址: https://play.min.io -#凭据: -#账号: minioadmin / 密码: minioadmin -#特点: -#由 MinIO 官方提供,用于演示和测试。 -#公开可访问,但数据可能定期清理。 -#支持 S3 API,适合快速验证代码 +# spdmadmin/spdmadmin 作为普通用户只能看到spdm桶的数据 minio: endpoint: 192.168.65.161 port: 9000 access-key: minioadmin secret-key: minioadmin secure: false - bucket-name: spdm \ No newline at end of file + secret-business-bucket: secretbusiness # 存放保密业务代码、脚本的桶(仅超级管理员访问) + spdm-bucket: spdm # 普通业务数据桶(分配给用户读写权限) \ No newline at end of file diff --git a/data/src/main/resources/application-local.yml b/data/src/main/resources/application-local.yml index f3089bd8..eb41ffc0 100644 --- a/data/src/main/resources/application-local.yml +++ b/data/src/main/resources/application-local.yml @@ -95,7 +95,8 @@ minio: access-key: minioadmin secret-key: minioadmin secure: false - bucket-name: spdm + secret-business-bucket: secretbusiness # 存放保密业务代码、脚本的桶(仅超级管理员访问) + spdm-bucket: spdm # 普通业务数据桶(分配给用户读写权限) management: diff --git a/data/src/main/resources/application-prod.yml b/data/src/main/resources/application-prod.yml index 009c80fb..a22712d0 100644 --- a/data/src/main/resources/application-prod.yml +++ b/data/src/main/resources/application-prod.yml @@ -148,4 +148,5 @@ minio: access-key: minioadmin secret-key: minioadmin secure: false - bucket-name: spdm \ No newline at end of file + secret-business-bucket: secretbusiness # 存放保密业务代码、脚本的桶(仅超级管理员访问) + spdm-bucket: spdm # 普通业务数据桶(分配给用户读写权限) \ No newline at end of file diff --git a/data/src/main/resources/application-test.yml b/data/src/main/resources/application-test.yml index 232164aa..b3aca0cf 100644 --- a/data/src/main/resources/application-test.yml +++ b/data/src/main/resources/application-test.yml @@ -146,4 +146,5 @@ minio: access-key: minioadmin secret-key: minioadmin secure: false - bucket-name: spdm + secret-business-bucket: secretbusiness # 存放保密业务代码、脚本的桶(仅超级管理员访问) + spdm-bucket: spdm # 普通业务数据桶(分配给用户读写权限) \ No newline at end of file