package storage import ( "context" "fmt" "io" "net/url" "time" "github.com/google/uuid" "github.com/minio/minio-go/v7" "github.com/minio/minio-go/v7/pkg/credentials" ) type MinioClient struct { client *minio.Client endpoint string } type Config struct { Endpoint string AccessKeyID string SecretAccessKey string UseSSL bool } func NewMinioClient(cfg Config) (*MinioClient, error) { client, err := minio.New(cfg.Endpoint, &minio.Options{ Creds: credentials.NewStaticV4(cfg.AccessKeyID, cfg.SecretAccessKey, ""), Secure: cfg.UseSSL, }) if err != nil { return nil, fmt.Errorf("minio client: %w", err) } return &MinioClient{client: client, endpoint: cfg.Endpoint}, nil } func (m *MinioClient) PresignedPutURL(ctx context.Context, bucket, key string, expiry time.Duration) (string, error) { u, err := m.client.PresignedPutObject(ctx, bucket, key, expiry) if err != nil { return "", err } return u.String(), nil } func (m *MinioClient) PresignedGetURL(ctx context.Context, bucket, key string, expiry time.Duration) (string, error) { reqParams := url.Values{} u, err := m.client.PresignedGetObject(ctx, bucket, key, expiry, reqParams) if err != nil { return "", err } return u.String(), nil } func (m *MinioClient) GenerateKey(folder string) string { return fmt.Sprintf("%s/%s", folder, uuid.New().String()) } func (m *MinioClient) DeleteObject(ctx context.Context, bucket, key string) error { return m.client.RemoveObject(ctx, bucket, key, minio.RemoveObjectOptions{}) } func (m *MinioClient) GetObject(ctx context.Context, bucket, key string) (io.ReadCloser, error) { obj, err := m.client.GetObject(ctx, bucket, key, minio.GetObjectOptions{}) if err != nil { return nil, err } return obj, nil } func (m *MinioClient) InitiateMultipartUpload(ctx context.Context, bucket, key string) (string, error) { // MinIO SDK doesn't directly expose multipart — use presigned PUT per chunk instead. // Return a generated upload ID for session tracking. return uuid.New().String(), nil }