package storage import ( "context" "io" "strings" "github.com/minio/minio-go/v7" "github.com/minio/minio-go/v7/pkg/credentials" "github.com/rs/zerolog/log" "github.com/spf13/viper" ) type MinioStorageHandler struct { *minio.Client BucketName string } func NewMinioStorageHandler(cfg *viper.Viper) (*MinioStorageHandler, error) { minioClient, err := minio.New(cfg.GetString("storage.files.minio.endpoint"), &minio.Options{ Creds: credentials.NewStaticV4(cfg.GetString("storage.files.minio.access_key"), cfg.GetString("storage.files.minio.secret_key"), ""), Secure: cfg.GetBool("storage.files.minio.use_ssl"), }) if err != nil { log.Error().Err(err).Msg("") return nil, err } return &MinioStorageHandler{ Client: minioClient, BucketName: cfg.GetString("storage.files.minio.bucket_name"), }, nil } func (s *MinioStorageHandler) Put(reader io.Reader, prefix string, filename string, size int64, metadata map[string]string) error { s.Client.PutObject(context.TODO(), s.BucketName, prefix+"/"+filename, reader, size, minio.PutObjectOptions{ UserMetadata: metadata, }) return nil } func (s *MinioStorageHandler) List(prefix string) []FileInfo { res := []FileInfo{} ctx, cancel := context.WithCancel(context.Background()) defer cancel() objectCh := s.Client.ListObjects(ctx, s.BucketName, minio.ListObjectsOptions{ Prefix: prefix, Recursive: true, }) for object := range objectCh { if object.Err != nil { log.Error().Str("prefix", prefix).Err(object.Err).Msg("Error listing files for prefix") continue } objinfo, err := s.Client.StatObject(context.Background(), s.BucketName, object.Key, minio.StatObjectOptions{}) if err != nil { log.Error().Err(err).Msg("") continue } path := strings.Split(object.Key, "/") fileinfo := FileInfo{ Key: object.Key, FileName: path[len(path)-1], LastModified: object.LastModified, ContentType: object.ContentType, Metadata: objinfo.UserMetadata, } res = append(res, fileinfo) } return res } func (s *MinioStorageHandler) Get(prefix string, file string) (io.Reader, *FileInfo, error) { object, err := s.Client.GetObject(context.Background(), s.BucketName, prefix+"/"+file, minio.GetObjectOptions{}) if err != nil { log.Error().Err(err).Msg("") return nil, nil, err } objinfo, err := s.Client.StatObject(context.Background(), s.BucketName, prefix+"/"+file, minio.StatObjectOptions{}) if err != nil { log.Error().Err(err).Msg("") return nil, nil, err } path := strings.Split(objinfo.Key, "/") fileinfo := &FileInfo{ Key: objinfo.Key, FileName: path[len(path)-1], LastModified: objinfo.LastModified, ContentType: objinfo.ContentType, Metadata: objinfo.UserMetadata, } return object, fileinfo, nil } func (s *MinioStorageHandler) Copy(src string, dst string) error { srcOpts := minio.CopySrcOptions{ Bucket: s.BucketName, Object: src, } // Destination object dstOpts := minio.CopyDestOptions{ Bucket: s.BucketName, Object: dst, } _, err := s.Client.CopyObject(context.Background(), dstOpts, srcOpts) if err != nil { log.Error().Err(err).Msg("") return err } return nil }