meti-backend/internal/service/file_service.go
Aditya Siregar 9e95e8ee5e Init Eslogad
2025-08-09 15:09:43 +07:00

93 lines
2.5 KiB
Go

package service
import (
"context"
"path/filepath"
"strings"
"time"
"eslogad-be/internal/contract"
"github.com/google/uuid"
)
type FileStorage interface {
Upload(ctx context.Context, bucket, key string, content []byte, contentType string) (string, error)
EnsureBucket(ctx context.Context, bucket string) error
}
type FileServiceImpl struct {
storage FileStorage
userProcessor UserProcessor
profileBucket string
docBucket string
}
func NewFileService(storage FileStorage, userProcessor UserProcessor, profileBucket, docBucket string) *FileServiceImpl {
return &FileServiceImpl{storage: storage, userProcessor: userProcessor, profileBucket: profileBucket, docBucket: docBucket}
}
func (s *FileServiceImpl) UploadProfileAvatar(ctx context.Context, userID uuid.UUID, filename string, content []byte, contentType string) (string, error) {
if err := s.storage.EnsureBucket(ctx, s.profileBucket); err != nil {
return "", err
}
ext := strings.ToLower(strings.TrimPrefix(filepath.Ext(filename), "."))
if ext := mimeExtFromContentType(contentType); ext != "" {
ext = ext
}
key := buildObjectKey("profile", userID, ext)
url, err := s.storage.Upload(ctx, s.profileBucket, key, content, contentType)
if err != nil {
return "", err
}
_, _ = s.userProcessor.UpdateUserProfile(ctx, userID, &contract.UpdateUserProfileRequest{AvatarURL: &url})
return url, nil
}
func (s *FileServiceImpl) UploadDocument(ctx context.Context, userID uuid.UUID, filename string, content []byte, contentType string) (string, string, error) {
if err := s.storage.EnsureBucket(ctx, s.docBucket); err != nil {
return "", "", err
}
ext := strings.ToLower(strings.TrimPrefix(filepath.Ext(filename), "."))
if ext := mimeExtFromContentType(contentType); ext != "" {
ext = ext
}
key := buildObjectKey("documents", userID, ext)
url, err := s.storage.Upload(ctx, s.docBucket, key, content, contentType)
if err != nil {
return "", "", err
}
return url, key, nil
}
func buildObjectKey(prefix string, userID uuid.UUID, ext string) string {
now := time.Now().UTC()
parts := []string{
prefix,
userID.String(),
now.Format("2006/01/02"),
uuid.New().String(),
}
key := strings.Join(parts, "/")
if ext != "" {
key += "." + ext
}
return key
}
func mimeExtFromContentType(ct string) string {
switch strings.ToLower(ct) {
case "image/jpeg", "image/jpg":
return "jpg"
case "image/png":
return "png"
case "image/webp":
return "webp"
case "application/pdf":
return "pdf"
default:
return ""
}
}