package logic import ( "context" "fmt" "path/filepath" "time" "git.cialloo.com/CiallooWeb/Blog/app/internal/svc" "git.cialloo.com/CiallooWeb/Blog/app/internal/types" "github.com/aws/aws-sdk-go-v2/service/s3" "github.com/google/uuid" "github.com/zeromicro/go-zero/core/logx" ) type UploadPresignedURLLogic struct { logx.Logger ctx context.Context svcCtx *svc.ServiceContext } // Get presigned URL for file upload func NewUploadPresignedURLLogic(ctx context.Context, svcCtx *svc.ServiceContext) *UploadPresignedURLLogic { return &UploadPresignedURLLogic{ Logger: logx.WithContext(ctx), ctx: ctx, svcCtx: svcCtx, } } func (l *UploadPresignedURLLogic) UploadPresignedURL(req *types.UploadPresignedURLReq) (resp *types.UploadPresignedURLResp, err error) { // Generate unique file key ext := filepath.Ext(req.FileName) fileKey := fmt.Sprintf("uploads/%s%s", uuid.New().String(), ext) // Calculate expiration time expiration := time.Duration(l.svcCtx.Config.S3.PresignedURLExpiration) * time.Second expireAt := time.Now().Add(expiration) // Create presigned client presignClient := s3.NewPresignClient(l.svcCtx.S3Client) // Generate presigned PUT URL putObjectInput := &s3.PutObjectInput{ Bucket: &l.svcCtx.Config.S3.Bucket, Key: &fileKey, } presignedReq, err := presignClient.PresignPutObject(l.ctx, putObjectInput, func(opts *s3.PresignOptions) { opts.Expires = expiration }) if err != nil { l.Errorf("Failed to generate presigned URL: %v", err) return nil, err } // Insert record into tmpfiles table query := `INSERT INTO tmpfiles (file_name, key, presigned_url, expiration) VALUES ($1, $2, $3, $4)` _, err = l.svcCtx.DB.ExecContext(l.ctx, query, req.FileName, fileKey, presignedReq.URL, expireAt) if err != nil { l.Errorf("Failed to insert tmpfile record: %v", err) return nil, err } return &types.UploadPresignedURLResp{ Url: presignedReq.URL, FileKey: fileKey, ExpireAt: expireAt.Unix(), }, nil }