package minio import ( "context" "io" "mime" "net/url" "strconv" "time" "go-socket/packages/config" "github.com/google/uuid" "github.com/minio/minio-go/v7" "github.com/minio/minio-go/v7/pkg/credentials" ) var minClient *minio.Client type DataType uint8 const ( ConnectionFile DataType = iota HubChannelFile UserAvatar UserProfileBg ) type DataTypePrefix string const ( ConnectionFilePrefix DataTypePrefix = "connection/" HubChannelFilePrefix DataTypePrefix = "hub/" UserAvatarPrefix DataTypePrefix = "userAvatar/" UserProfileBgPrefix DataTypePrefix = "userProfileBg/" ) type GetKeyOptions struct { UserId uuid.UUID ConnectionId uuid.UUID ChannelId uuid.UUID MimeType string UploadType DataType } func GetKey(opts GetKeyOptions) string { extensions, err := mime.ExtensionsByType(opts.MimeType) if err != nil || len(extensions) == 0 { extensions = []string{".unknown"} } key := "/" + strconv.FormatInt(time.Now().UnixMilli(), 10) + extensions[0] switch opts.UploadType { case HubChannelFile: return string(HubChannelFilePrefix) + opts.ChannelId.String() + key case UserAvatar: return string(UserAvatarPrefix) + opts.UserId.String() + key case UserProfileBg: return string(UserProfileBgPrefix) + opts.UserId.String() + key default: return string(ConnectionFilePrefix) + opts.ConnectionId.String() + key } } func Init(ctx context.Context) { var err error minClient, err = minio.New("localhost:9000", &minio.Options{ Creds: credentials.NewStaticV4("root", "change_to_env", ""), Secure: false, }) // TODO change for production if err != nil { panic(err) } exists, err := minClient.BucketExists(ctx, config.FileStorageBucketName) if err != nil { panic(err) } if !exists { err = minClient.MakeBucket(ctx, config.FileStorageBucketName, minio.MakeBucketOptions{}) if err != nil { exists, checkErr := minClient.BucketExists(ctx, config.FileStorageBucketName) if checkErr != nil || !exists { panic(err) } } } } func Upload(ctx context.Context, key string, body io.Reader, size int64, contentType string, metadata map[string]string) error { opt := minio.PutObjectOptions{ ContentType: contentType, PartSize: config.FileProcessingPartBytes, NumThreads: config.FileProcessingThreads, UserMetadata: metadata, } opt.SetMatchETagExcept("*") _, err := minClient.PutObject(ctx, config.FileStorageBucketName, key, body, size, opt) return err } func GetDownloadUrlAndMetadata(ctx context.Context, key string) (*url.URL, map[string]string, error) { info, err := minClient.StatObject(ctx, config.FileStorageBucketName, key, minio.StatObjectOptions{}) if err != nil { return nil, nil, err } u, err := minClient.PresignedGetObject(ctx, config.FileStorageBucketName, key, config.FileDownloadLinkTtl, nil) if err != nil { return nil, nil, err } return u, info.UserMetadata, nil } func DoesExist(ctx context.Context, key string) bool { _, err := minClient.StatObject(ctx, config.FileStorageBucketName, key, minio.StatObjectOptions{}) return err == nil } func Delete(ctx context.Context, key string) error { err := minClient.RemoveObject(ctx, config.FileStorageBucketName, key, minio.RemoveObjectOptions{}) return err }