l_ai_knowledge/internal/application/service/file/cos.go

84 lines
2.5 KiB
Go

package file
import (
"context"
"fmt"
"io"
"mime/multipart"
"net/http"
"net/url"
"path/filepath"
"strings"
"github.com/google/uuid"
"github.com/tencentyun/cos-go-sdk-v5"
"knowlege-lsxd/internal/types/interfaces"
)
// cosFileService implements the FileService interface for Tencent Cloud COS
type cosFileService struct {
client *cos.Client
bucketURL string
cosPathPrefix string
}
// NewCosFileService creates a new COS file service instance
func NewCosFileService(appId, region, secretId, secretKey, cosPathPrefix string) (interfaces.FileService, error) {
bucketURL := fmt.Sprintf("https://%s.cos.%s.myqcloud.com", appId, region)
u, err := url.Parse(bucketURL)
if err != nil {
return nil, fmt.Errorf("failed to parse bucketURL: %w", err)
}
b := &cos.BaseURL{BucketURL: u}
client := cos.NewClient(b, &http.Client{
Transport: &cos.AuthorizationTransport{
SecretID: secretId,
SecretKey: secretKey,
},
})
return &cosFileService{
client: client,
bucketURL: bucketURL,
cosPathPrefix: cosPathPrefix,
}, nil
}
// SaveFile saves a file to COS storage
// It generates a unique name for the file and organizes it by tenant and knowledge ID
func (s *cosFileService) SaveFile(ctx context.Context,
file *multipart.FileHeader, tenantID uint, knowledgeID string,
) (string, error) {
ext := filepath.Ext(file.Filename)
objectName := fmt.Sprintf("%s/%d/%s/%s%s", s.cosPathPrefix, tenantID, knowledgeID, uuid.New().String(), ext)
src, err := file.Open()
if err != nil {
return "", fmt.Errorf("failed to open file: %w", err)
}
defer src.Close()
_, err = s.client.Object.Put(ctx, objectName, src, nil)
if err != nil {
return "", fmt.Errorf("failed to upload file to COS: %w", err)
}
return fmt.Sprintf("https://%s/%s", s.bucketURL, objectName), nil
}
// GetFile retrieves a file from COS storage by its path URL
func (s *cosFileService) GetFile(ctx context.Context, filePathUrl string) (io.ReadCloser, error) {
objectName := strings.TrimPrefix(filePathUrl, s.bucketURL)
resp, err := s.client.Object.Get(ctx, objectName, nil)
if err != nil {
return nil, fmt.Errorf("failed to get file from COS: %w", err)
}
return resp.Body, nil
}
// DeleteFile removes a file from COS storage
func (s *cosFileService) DeleteFile(ctx context.Context, filePath string) error {
objectName := strings.TrimPrefix(filePath, s.bucketURL)
_, err := s.client.Object.Delete(ctx, objectName)
if err != nil {
return fmt.Errorf("failed to delete file: %w", err)
}
return nil
}