qudoco-be/utils/storage/cms_upload.go

77 lines
2.1 KiB
Go
Raw Normal View History

2026-04-10 07:23:24 +00:00
package storage
import (
"context"
"fmt"
"mime"
"mime/multipart"
"path/filepath"
"strings"
"time"
"github.com/google/uuid"
"github.com/minio/minio-go/v7"
appcfg "web-qudo-be/config/config"
)
// CMSPreviewURL is the absolute URL served by this API (GET /cms-media/viewer/...) for DB image_url / media_url fields.
func CMSPreviewURL(cfg *appcfg.Config, objectKey string) string {
base := cfg.APIPublicBaseURL()
key := strings.TrimPrefix(strings.TrimSpace(objectKey), "/")
return base + "/cms-media/viewer/" + key
}
2026-04-10 07:23:24 +00:00
var imageExts = map[string]bool{
".jpg": true, ".jpeg": true, ".png": true, ".gif": true, ".webp": true,
}
var mediaExts = map[string]bool{
".jpg": true, ".jpeg": true, ".png": true, ".gif": true, ".webp": true,
".mp4": true, ".webm": true,
}
// UploadCMSObject stores a file in MinIO under cms/{folder}/YYYY/MM/{uuid}{ext} and returns object key + preview URL (API viewer, not direct MinIO).
func UploadCMSObject(ms *appcfg.MinioStorage, folder string, file *multipart.FileHeader, allowVideo bool) (objectKey string, previewURL string, err error) {
2026-04-10 07:23:24 +00:00
if file == nil {
return "", "", fmt.Errorf("file is required")
}
ext := strings.ToLower(filepath.Ext(file.Filename))
if allowVideo {
if !mediaExts[ext] {
return "", "", fmt.Errorf("unsupported file type (allowed: images, mp4, webm)")
}
} else if !imageExts[ext] {
return "", "", fmt.Errorf("unsupported image type")
}
client, err := ms.ConnectMinio()
if err != nil {
return "", "", err
}
src, err := file.Open()
if err != nil {
return "", "", err
}
defer src.Close()
bucket := ms.Cfg.ObjectStorage.MinioStorage.BucketName
now := time.Now()
objectKey = fmt.Sprintf("cms/%s/%d/%02d/%s%s", folder, now.Year(), int(now.Month()), uuid.New().String(), ext)
contentType := mime.TypeByExtension(ext)
if contentType == "" {
contentType = "application/octet-stream"
}
_, err = client.PutObject(context.Background(), bucket, objectKey, src, file.Size, minio.PutObjectOptions{
ContentType: contentType,
})
if err != nil {
return "", "", err
}
return objectKey, CMSPreviewURL(ms.Cfg, objectKey), nil
2026-04-10 07:23:24 +00:00
}