package miniohelper import ( "context" "errors" "fmt" "net/url" "path" m "simrs-vx/internal/infra/minio" "github.com/minio/minio-go/v7" ) type minioRepository struct { client *minio.Client } var I minioRepository = minioRepository{} func (repo *minioRepository) SetClient() { repo.client = m.I } // Check exist bucket if not exist create Bucket func (repo *minioRepository) createBucket(bucketName string, region string) error { exist, err := repo.client.BucketExists(context.Background(), bucketName) if err != nil { return err } if !exist { // create bucket if err := repo.client.MakeBucket(context.Background(), bucketName, minio.MakeBucketOptions{Region: region}); err != nil { return err } // set bucket policy to public read policy := fmt.Sprintf(`{ "Version": "2012-10-17", "Statement": [ { "Effect": "Allow", "Principal": {"AWS": ["*"]}, "Action": ["s3:GetObject"], "Resource": ["arn:aws:s3:::%s/*"] } ] }`, bucketName) if err := repo.client.SetBucketPolicy(context.Background(), bucketName, policy); err != nil { return err } } return nil } // Upload file reader to MinIO func (repo *minioRepository) PutObject(input UploadReaderInput) (*minio.UploadInfo, error) { if err := repo.createBucket(input.BucketName, m.O.GetRegion()); err != nil { return nil, err } options := minio.PutObjectOptions{ ContentType: input.ContentType, UserMetadata: map[string]string{"x-amz-acl": "public-read"}, } uploadInfo, err := repo.client.PutObject(context.Background(), input.BucketName, input.Name, input.File, input.Size, options) if err != nil { return nil, err } return &uploadInfo, err } // Upload file path to MinIO func (repo *minioRepository) FPutObject(input UploadPathInput) (*minio.UploadInfo, error) { if err := repo.createBucket(input.BucketName, m.O.GetRegion()); err != nil { return nil, err } options := minio.PutObjectOptions{ ContentType: input.ContentType, UserMetadata: map[string]string{"x-amz-acl": "public-read"}, } uploadInfo, err := repo.client.FPutObject(context.Background(), input.BucketName, input.Name, input.Path, options) if err != nil { return nil, err } return &uploadInfo, err } // Move file from old to new MinIO path func (repo *minioRepository) MoveObject(src minio.CopySrcOptions, dst minio.CopyDestOptions) (*minio.UploadInfo, error) { uploadInfo, err := repo.client.CopyObject(context.Background(), dst, src) if err != nil { return nil, err } if err := repo.RemoveObject(src.Bucket, src.Object); err != nil { return nil, err } return &uploadInfo, err } // Generatet public link MinIO func (repo *minioRepository) GenerateUrl(bucket, object string) string { mode := "http" if m.O.GetUseSsl() { mode = "https" } return fmt.Sprintf("%s://%s/%s/%s", mode, m.O.GetEndpoint(), bucket, object) } // Download file from MinIO func (repo *minioRepository) GetObject(bucket string, fileName string) (*minio.Object, error) { object, err := repo.client.GetObject(context.Background(), bucket, fileName, minio.GetObjectOptions{}) if err != nil { return nil, err } return object, nil } // Delete file from MinIO func (repo *minioRepository) RemoveObject(bucket string, fileName string) error { if err := repo.client.RemoveObject(context.Background(), bucket, fileName, minio.RemoveObjectOptions{}); err != nil { return err } return nil } // create presigned url to post object with custom policy func (repo *minioRepository) GeneratePresignedPost(policy *minio.PostPolicy) (*url.URL, map[string]string, error) { presignedUrl, formData, err := repo.client.PresignedPostPolicy(context.Background(), policy) if err != nil { return nil, nil, err } return presignedUrl, formData, nil } // create presigned url to get object func (repo *minioRepository) GeneratePresignedGetObject(input PresignedGetInput) (*url.URL, error) { presignedUrl, err := repo.client.PresignedGetObject(context.Background(), input.Bucket, input.Object, input.Expiry, input.ReqParams) if err != nil { return nil, err } return presignedUrl, nil } func getBucketName(idx int) string { return m.O.GetBucketName()[idx] } func GetBucketPatient() (string, error) { bucketName := getBucketName(0) if bucketName == "" { return "", errors.New("bucket name unknown") } return bucketName, nil } func GetEndpointUrl(bucket string) string { mode := "http" if m.O.GetUseSsl() { mode = "https" } return fmt.Sprintf("%s://%s/%s", mode, m.O.GetEndpoint(), bucket) } func GetFilename(rawUrl string) (string, error) { parsed, err := url.Parse(rawUrl) if err != nil { return "", err } return path.Base(parsed.Path), nil }