package minio import ( "context" "fmt" "fwh-toolbox-server/config" "io" "log" "net/url" "strings" "time" "github.com/minio/minio-go/v7" "github.com/minio/minio-go/v7/pkg/credentials" "go.uber.org/zap" ) var Client *minio.Client var BucketName string type ObjectInfo = minio.ObjectInfo func InitClient(cfg *config.AppConfig) { var err error Client, err = minio.New(cfg.MinIoEndpoint, &minio.Options{ Creds: credentials.NewStaticV4(cfg.MinioAccessKey, cfg.MinioSecretKey, ""), Secure: strings.HasPrefix(strings.ToLower(cfg.MinIoEndpoint), "https://"), }) if err != nil { log.Fatalln("❌ Failed to init MinIO client") panic(err) } BucketName = cfg.MinioBucketName ctx := context.Background() bucketInfo, err := Client.ListBuckets(ctx) if err != nil { log.Fatalln("❌ List Buckets failed") panic(err) } log.Println("Exists Bucket:") for _, info := range bucketInfo { log.Printf("%s\n", info.Name) } exists, err := Client.BucketExists(ctx, BucketName) if err != nil { log.Fatalf("❌ Bucket check failed: %s\n", BucketName) panic(err) } if !exists { err = Client.MakeBucket(ctx, BucketName, minio.MakeBucketOptions{}) if err != nil { log.Fatalln("❌ Failed to create bucket") panic(err) } log.Println("✅ Created bucket:", BucketName) } else { log.Println("✅ Using existing bucket:", BucketName) } } func UploadFile(localPath, objectName string) error { ctx := context.Background() info, err := Client.FPutObject(ctx, BucketName, objectName, localPath, minio.PutObjectOptions{}) if err != nil { return err } zap.L().Info(fmt.Sprintf("✅ Uploaded %s (%d bytes)", info.Key, info.Size)) return nil } func DownloadFile(objectName, localPath string) error { ctx := context.Background() return Client.FGetObject(ctx, BucketName, objectName, localPath, minio.GetObjectOptions{}) } func ListFiles(prefix string, recursive bool) ([]string, error) { ctx := context.Background() var result []string for obj := range Client.ListObjects(ctx, BucketName, minio.ListObjectsOptions{ Prefix: prefix, // 遍历 prefix 目录 Recursive: recursive, // true - 递归所有文件, false - 只列出当前层级 }) { if obj.Err != nil { return nil, obj.Err } result = append(result, obj.Key) } return result, nil } func ListAllFiles() ([]string, error) { ctx := context.Background() var result []string for obj := range Client.ListObjects(ctx, BucketName, minio.ListObjectsOptions{Recursive: true}) { if obj.Err != nil { return nil, obj.Err } result = append(result, obj.Key) } return result, nil } func DeleteFile(objectName string) error { ctx := context.Background() return Client.RemoveObject(ctx, BucketName, objectName, minio.RemoveObjectOptions{}) } func GetObject(objectName string) (*minio.Object, error) { ctx := context.Background() return Client.GetObject(ctx, BucketName, objectName, minio.GetObjectOptions{}) } // StatObject 会验证对象是否存在,您是否拥有访问该对象的权限,并返回有关该对象的信息。 func StatObject(objectName string) (minio.ObjectInfo, error) { ctx := context.Background() return Client.StatObject(ctx, BucketName, objectName, minio.StatObjectOptions{}) } // 生成临时下载链接 func GetPresignedURL(objectName string, expire time.Duration) (*url.URL, error) { ctx := context.Background() return Client.PresignedGetObject(ctx, BucketName, objectName, expire, nil) } // 从流上传(用于HTTP上传) func UploadFromReader(file io.Reader, size int64, objectName, contentType string) error { ctx := context.Background() info, err := Client.PutObject(ctx, BucketName, objectName, file, size, minio.PutObjectOptions{ ContentType: contentType, }) if err != nil { return err } zap.L().Info(fmt.Sprintf("✅ Uploaded %s (%d bytes)", info.Key, info.Size)) return nil } // 判断文件是否存在 func ExistsObject(objectName string) (bool, error) { _, err := StatObject(objectName) if err != nil { // 对象不存在的判断(最常见) if minio.ToErrorResponse(err).Code == "NoSuchKey" { log.Printf("Object(%s) does NOT exist\n", objectName) return false, nil } return false, err } return true, nil }