minio分权限存储
This commit is contained in:
2
.idea/compiler.xml
generated
2
.idea/compiler.xml
generated
@@ -15,6 +15,7 @@
|
||||
<module name="task" />
|
||||
<module name="common" />
|
||||
<module name="data" />
|
||||
<module name="submit" />
|
||||
<module name="approve" />
|
||||
<module name="project" />
|
||||
<module name="gateway" />
|
||||
@@ -33,6 +34,7 @@
|
||||
<module name="pbs" options="-parameters" />
|
||||
<module name="performance" options="-parameters" />
|
||||
<module name="project" options="-parameters" />
|
||||
<module name="submit" options="-parameters" />
|
||||
<module name="system" options="-parameters" />
|
||||
<module name="task" options="-parameters" />
|
||||
</option>
|
||||
|
||||
1
.idea/encodings.xml
generated
1
.idea/encodings.xml
generated
@@ -12,6 +12,7 @@
|
||||
<file url="file://$PROJECT_DIR$/project/src/main/java" charset="UTF-8" />
|
||||
<file url="file://$PROJECT_DIR$/src/main/java" charset="UTF-8" />
|
||||
<file url="file://$PROJECT_DIR$/src/main/resources" charset="UTF-8" />
|
||||
<file url="file://$PROJECT_DIR$/submit/src/main/java" charset="UTF-8" />
|
||||
<file url="file://$PROJECT_DIR$/system/src/main/java" charset="UTF-8" />
|
||||
<file url="file://$PROJECT_DIR$/task/src/main/java" charset="UTF-8" />
|
||||
</component>
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -3,7 +3,6 @@ package com.sdm.common.entity.enums;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
|
||||
@Schema(description = "文件业务类型枚举")
|
||||
|
||||
public enum FileBizTypeEnum {
|
||||
/**
|
||||
* 模型文件
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -83,6 +83,13 @@
|
||||
<version>8.5.7</version> <!-- 使用最新版本 -->
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.minio</groupId>
|
||||
<artifactId>minio-admin</artifactId>
|
||||
<version>8.5.7</version> <!-- 可根据最新版本替换 -->
|
||||
</dependency>
|
||||
|
||||
|
||||
<!-- Apache Commons IO 用于流操作 -->
|
||||
<dependency>
|
||||
<groupId>commons-io</groupId>
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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")
|
||||
|
||||
@@ -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<String> 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<String, String> 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());
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
|
||||
/**
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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<String> memberOf;
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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;
|
||||
|
||||
/**
|
||||
* 文件大小
|
||||
|
||||
@@ -200,6 +200,15 @@ public interface IDataFileService {
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* 上传脚本文件
|
||||
* @param scriptFile 脚本
|
||||
* @return 上传文件id
|
||||
*/
|
||||
default SdmResponse<Long> uploadScriptFile(MultipartFile scriptFile){
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* 图片预览
|
||||
*
|
||||
|
||||
@@ -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<String, String> tags);
|
||||
|
||||
/**
|
||||
* 上传文件到MinIO
|
||||
* @param file 文件对象
|
||||
* @param objectName 文件名(objectKey)
|
||||
* @param tags 文件标签
|
||||
* @param bucketName 桶名称
|
||||
*/
|
||||
public void uploadFile(MultipartFile file, String objectName, Map<String, String> 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<String> queryFilesByTags(Map<String, String> tags) throws Exception;
|
||||
|
||||
/**
|
||||
* 根据标签查询文件
|
||||
*/
|
||||
List<String> queryFilesByTags(Map<String, String> tags, String bucketName) throws Exception;
|
||||
|
||||
String getMinioPresignedUrl(String objectKey);
|
||||
String getMinioPresignedUrl(String objectKey, String bucketName);
|
||||
|
||||
}
|
||||
}
|
||||
@@ -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<FileStorage> page = new PageInfo<>(list);
|
||||
return PageUtils.getJsonObjectSdmResponse(list, page);
|
||||
|
||||
@@ -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<String> 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<String> listAllUsers()
|
||||
throws NoSuchAlgorithmException, InvalidKeyException, IOException, InvalidCipherTextException {
|
||||
Map<String, UserInfo> userMap = minioAdminClient.listUsers();
|
||||
return new ArrayList<>(userMap.keySet());
|
||||
}
|
||||
|
||||
/**
|
||||
* 列出所有MinIO访问策略
|
||||
*
|
||||
* @return 策略名称列表
|
||||
* @throws NoSuchAlgorithmException 无此算法异常
|
||||
* @throws InvalidKeyException 无效密钥异常
|
||||
* @throws IOException IO异常
|
||||
*/
|
||||
public Map<String,String> listAllPolicies() throws NoSuchAlgorithmException, InvalidKeyException, IOException {
|
||||
Map<String,String> 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<String, UserInfo> 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;
|
||||
}
|
||||
}
|
||||
@@ -65,9 +65,11 @@ import java.util.stream.Collectors;
|
||||
@Slf4j
|
||||
@Service
|
||||
public class MinioFileIDataFileServiceImpl implements IDataFileService {
|
||||
private static final List<DirTypeEnum> INIT_DIR = List.of(
|
||||
// 初始化用户业务库目录
|
||||
private static final List<DirTypeEnum> 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<Integer> 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<PageDataResp<List<FileStorage>>> searchResult = dataStorageAnalysis.listBigFile(queryBigFileReq);
|
||||
PageDataResp<List<FileStorage>> pageDataResp = searchResult.getData();
|
||||
List<FileStorage> 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<Long> uploadScriptFile(MultipartFile scriptFile) {
|
||||
// 先创建 script 目录
|
||||
String dirMinioObjectKey = getDirMinioObjectKey(DirTypeEnum.SCRIPT_DIR.getDirName());
|
||||
Optional<FileMetadataInfo> 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);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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<Result<Item>> 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<Result<DeleteError>> 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<String, String> 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<String, String> tags, String bucketName) {
|
||||
try {
|
||||
// 检查存储桶是否存在,不存在则创建
|
||||
createBucketIfNotExists();
|
||||
// 检查存储桶是否存在,不存在则创建(为了向后兼容,仍然保留此处检查)
|
||||
createBucketIfNotExists(bucketName);
|
||||
|
||||
// 转换标签为MinIO格式
|
||||
Map<String, String> 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<String, String> 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<String> queryFilesByTags(Map<String, String> tags) throws Exception {
|
||||
public List<String> queryFilesByTags(Map<String, String> tags, String bucketName) throws Exception {
|
||||
|
||||
List<String> result = new ArrayList<>();
|
||||
Iterable<Result<Item>> results = minioClient.listObjects(
|
||||
ListObjectsArgs.builder()
|
||||
.bucket(minioConfig.getBucketName())
|
||||
.bucket(bucketName)
|
||||
.build());
|
||||
|
||||
for (Result<Item> itemResult : results) {
|
||||
@@ -268,6 +359,13 @@ public class MinioService implements IMinioService {
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据标签查询文件(默认使用spdmBucket)
|
||||
*/
|
||||
public List<String> queryFilesByTags(Map<String, String> 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);
|
||||
|
||||
@@ -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
|
||||
secret-business-bucket: secretbusiness # 存放保密业务代码、脚本的桶(仅超级管理员访问)
|
||||
spdm-bucket: spdm # 普通业务数据桶(分配给用户读写权限)
|
||||
@@ -95,7 +95,8 @@ minio:
|
||||
access-key: minioadmin
|
||||
secret-key: minioadmin
|
||||
secure: false
|
||||
bucket-name: spdm
|
||||
secret-business-bucket: secretbusiness # 存放保密业务代码、脚本的桶(仅超级管理员访问)
|
||||
spdm-bucket: spdm # 普通业务数据桶(分配给用户读写权限)
|
||||
|
||||
|
||||
management:
|
||||
|
||||
@@ -148,4 +148,5 @@ minio:
|
||||
access-key: minioadmin
|
||||
secret-key: minioadmin
|
||||
secure: false
|
||||
bucket-name: spdm
|
||||
secret-business-bucket: secretbusiness # 存放保密业务代码、脚本的桶(仅超级管理员访问)
|
||||
spdm-bucket: spdm # 普通业务数据桶(分配给用户读写权限)
|
||||
@@ -146,4 +146,5 @@ minio:
|
||||
access-key: minioadmin
|
||||
secret-key: minioadmin
|
||||
secure: false
|
||||
bucket-name: spdm
|
||||
secret-business-bucket: secretbusiness # 存放保密业务代码、脚本的桶(仅超级管理员访问)
|
||||
spdm-bucket: spdm # 普通业务数据桶(分配给用户读写权限)
|
||||
Reference in New Issue
Block a user