package dj import ( "context" "fmt" "github.com/aws/aws-sdk-go/aws" awscs "github.com/aws/aws-sdk-go/aws/credentials" "github.com/aws/aws-sdk-go/aws/session" "github.com/aws/aws-sdk-go/service/sts" "github.com/gogf/gf/v2/frame/g" "github.com/minio/minio-go/v7" "github.com/minio/minio-go/v7/pkg/credentials" "log" "os" "path/filepath" "time" ) //// minio的配置信息 //const ( // Endpoint string = coryCommon.Global + ":9999" // AccessKeyID string = "admin" // SecretAccessKey string = "12345678" // BucketName string = "cory-create" // RoleARN string = "arn:aws:s3:::cory-create/*" // RoleSessionName string = "anysession" // Region string = "cn-chengdu" // UseSSL bool = true // DurationSeconds int64 = 3600 // // // Endpoint string = "jl.yj-3d.com:8154" // // AccessKeyID string = "minioadmin" // // SecretAccessKey string = "minioadmin" // // BucketName string = "cory-create" // // RoleARN string = "arn:aws:s3:::cory-create/*" // // RoleSessionName string = "anysession" // // Region string = "cn-chengdu" // // UseSSL bool = true // // DurationSeconds int64 = 3600 //) var ( Endpoint string AccessKeyID string SecretAccessKey string BucketName string RoleARN string RoleSessionName string Region string UseSSL bool DurationSeconds int64 ) func init() { Endpoint = g.Cfg().MustGet(context.Background(), "minio.endpoint").String() AccessKeyID = g.Cfg().MustGet(context.Background(), "minio.accessKeyID").String() SecretAccessKey = g.Cfg().MustGet(context.Background(), "minio.secretAccessKey").String() BucketName = g.Cfg().MustGet(context.Background(), "minio.bucketName").String() RoleSessionName = g.Cfg().MustGet(context.Background(), "minio.roleSessionName").String() Region = g.Cfg().MustGet(context.Background(), "minio.region").String() UseSSL = g.Cfg().MustGet(context.Background(), "minio.useSSL").Bool() DurationSeconds = g.Cfg().MustGet(context.Background(), "minio.durationSeconds").Int64() RoleARN = g.Cfg().MustGet(context.Background(), "minio.roleARN").String() } var ( IsEnablingSSL = false //是否开启SSL安全 (只针对初始化客户端) ) // PublicMinioClient 初始化MinIO客户端 func PublicMinioClient() (minioClient *minio.Client, err error) { // 获取临时凭证 token, accessKey, secretAccessKey := MinioVoucher() // 初始化MinIO客户端 minioClient, err = minio.New(Endpoint, &minio.Options{ Creds: credentials.NewStaticV4(accessKey, secretAccessKey, token), Secure: IsEnablingSSL, }) return } // MinioVoucher 获取minio的临时凭证 func MinioVoucher() (sessionToken, accessKey, secretKey string) { // 创建AWS会话 sess, err := session.NewSession(&aws.Config{ Endpoint: aws.String(Endpoint), DisableSSL: aws.Bool(UseSSL), Region: aws.String(Region), Credentials: awscs.NewStaticCredentials(AccessKeyID, SecretAccessKey, ""), }) if err != nil { log.Printf("创建AWS会话错误:%v", err) return } // 创建STS服务客户端 stsSvc := sts.New(sess) // 获取STS凭证 input := &sts.AssumeRoleInput{ RoleArn: aws.String(RoleARN), RoleSessionName: aws.String(RoleSessionName), DurationSeconds: aws.Int64(DurationSeconds), } result, err := stsSvc.AssumeRole(input) if err != nil { fmt.Println("获取STS凭证错误:", err) return } // 获取STS凭证的Token、AccessKey和SecretKey sessionToken = *result.Credentials.SessionToken accessKey = *result.Credentials.AccessKeyId secretKey = *result.Credentials.SecretAccessKey return } /* TheTemporaryAccessUrlIsObtainedBasedOnThePrefixOfTheSpecifiedBucket 根据指定桶的前缀获取到临时访问URL bucketName:桶名 prefix:前缀 expiry:URL能够访问的时间(最长7天或至少1秒) expiry := 3 * 24 * time.Hour 3天时间访问Url isRecursion:是否递归 */ func TheTemporaryAccessUrlIsObtainedBasedOnThePrefixOfTheSpecifiedBucket(ctx context.Context, minioClient *minio.Client, bucketName string, prefix string, expiry time.Duration, isRecursion bool) (url []string) { //1、获取递归集 objectSet := ListAndGenerateURLs(ctx, minioClient, bucketName, prefix, isRecursion) //2、根据集获取到临时可访问的URL for _, object := range objectSet { preSignature := GenerateAnOnlineScopedUrlBasedOnTheObject(ctx, minioClient, bucketName, object.Key, expiry) url = append(url, preSignature) } return } /* DownloadTheFileWithTheSpecifiedPrefixBasedOnTheObjectSet 根据对象集下载指定前缀的文件 bucketName:桶名 prefix:前缀 filePath:下载后保存路径 isRecursion:是否递归获取对象集 */ func DownloadTheFileWithTheSpecifiedPrefixBasedOnTheObjectSet(ctx context.Context, minioClient *minio.Client, bucketName string, prefix string, filePath string, isRecursion bool) (err error) { objectList := ListAndGenerateURLs(ctx, minioClient, bucketName, prefix, isRecursion) for _, object := range objectList { //split := strings.Split(object.Key, "/") //wz := split[len(split)-1] //fileName := strings.Split(wz, ".")[0] //if strings.Contains(fileName, "W") { // fmt.Println(wz) //} err = minioClient.FGetObject(ctx, bucketName, object.Key, filepath.ToSlash(filePath+"/"+object.Key), minio.GetObjectOptions{}) if err != nil { fmt.Println("下载minio资源失败:", err) return err } } return } /* DeletesTheFileWithTheSpecifiedPrefixBasedOnTheObjectSet 根据对象集删除指定前缀的文件 bucketName:桶名 prefix:前缀 isRecursion:是否递归获取对象集 */ func DeletesTheFileWithTheSpecifiedPrefixBasedOnTheObjectSet(ctx context.Context, minioClient *minio.Client, bucketName string, prefix string, isRecursion bool) (err error) { objectList := ListAndGenerateURLs(ctx, minioClient, bucketName, prefix, isRecursion) for _, object := range objectList { err = minioClient.RemoveObject(ctx, bucketName, object.Key, minio.RemoveObjectOptions{}) if err != nil { fmt.Println("删除minio资源失败:", err) return err } } return } /* UploadDataAccordingToTemporaryCredentials 根据临时凭证上传数据 filePath:本地文件路径 objectName:存储到minio的地址(桶+前缀) 示例:cory-create/uav/key.txt */ func UploadDataAccordingToTemporaryCredentials(filePath string, objectName string) (err error) { minioClient, err := PublicMinioClient() if err != nil { return } // 打开文件 file, err := os.Open(filePath) if err != nil { fmt.Println("Error opening file:", err) return } defer file.Close() // 使用minio-go的PutObject方法上传文件 n, err := minioClient.PutObject(context.Background(), BucketName, objectName, file, -1, minio.PutObjectOptions{}) if err != nil { fmt.Println("Error uploading file:", err) return } fmt.Printf("Successfully uploaded %s of size %d\n", objectName, n) return err } //========================================================================================================================= //========================================================================================================================= //========================================================================================================================= //========================================================================================================================= //========================================================================================================================= //========================================================================================================================= //========================================================================================================================= //========================================================================================================================= /* ListAndGenerateURLs 获取指定前缀下的对象集 bucketName:桶名 prefix:前缀(获取哪个下面的对象集) 示例:"uav/9b0af64e1c274105b157a9781961ed99/DJI_202405170903_001_9b0af64e1c274105b157a9781961ed99" isRecursion:是否递归 */ func ListAndGenerateURLs(ctx context.Context, minioClient *minio.Client, bucketName string, prefix string, isRecursion bool) (objectInfo []minio.ObjectInfo) { // 设置递归为 true,以获取所有对象,包括子目录中的对象 objectCh := minioClient.ListObjects(ctx, bucketName, minio.ListObjectsOptions{ Prefix: prefix, Recursive: isRecursion, }) // 等待通道中的对象被填充 for object := range objectCh { if object.Err != nil { fmt.Println("获取对象列表失败:", object.Err) continue } objectInfo = append(objectInfo, object) //fmt.Println("对象名称:", object.Key) } return } // GenerateAnOnlineScopedUrlBasedOnTheObject 根据对象集生成可在线访问的URL func GenerateAnOnlineScopedUrlBasedOnTheObject(ctx context.Context, minioClient *minio.Client, bucketName string, objectName string, expiry time.Duration) string { // 生成预签名的 GET URL presignedURL, err := minioClient.PresignedGetObject(ctx, bucketName, objectName, expiry, nil) if err != nil { log.Fatalf("生成预签名 URL 失败:%v", err) } //// 使用预签名 URL 访问对象 //resp, err := minioClie. //nt.GetObject(ctx, bucketName, objectName, minio.GetObjectOptions{}) //if err != nil { // log.Fatalf("获取对象失败:%v", err) //} //defer resp.Close() return presignedURL.String() } // StatObjectFunc 获取对象的元数据 func StatObjectFunc(ctx context.Context, minioClient *minio.Client, bucketName string, objectName string) (objInfo minio.ObjectInfo, err error) { objInfo, err = minioClient.StatObject(ctx, bucketName, objectName, minio.GetObjectOptions{}) return }