mirror of https://github.com/chaitin/PandaWiki.git
189 lines
4.1 KiB
Go
189 lines
4.1 KiB
Go
package usecase
|
|
|
|
import (
|
|
"bytes"
|
|
"context"
|
|
"fmt"
|
|
"io"
|
|
"mime"
|
|
"mime/multipart"
|
|
"path/filepath"
|
|
"strings"
|
|
|
|
"github.com/google/uuid"
|
|
"github.com/minio/minio-go/v7"
|
|
|
|
"github.com/chaitin/panda-wiki/config"
|
|
"github.com/chaitin/panda-wiki/domain"
|
|
"github.com/chaitin/panda-wiki/log"
|
|
"github.com/chaitin/panda-wiki/store/s3"
|
|
)
|
|
|
|
type FileUsecase struct {
|
|
logger *log.Logger
|
|
s3Client *s3.MinioClient
|
|
config *config.Config
|
|
}
|
|
|
|
func NewFileUsecase(logger *log.Logger, s3Client *s3.MinioClient, config *config.Config) *FileUsecase {
|
|
return &FileUsecase{
|
|
s3Client: s3Client,
|
|
logger: logger.WithModule("usecase.file"),
|
|
config: config,
|
|
}
|
|
}
|
|
|
|
func (u *FileUsecase) UploadFileGetUrl(ctx context.Context, kbID string, file *multipart.FileHeader) (string, error) {
|
|
key, err := u.UploadFile(ctx, kbID, file)
|
|
if err != nil {
|
|
return "", err
|
|
}
|
|
return fmt.Sprintf("http://panda-wiki-minio:9000/static-file/%s", key), nil
|
|
}
|
|
|
|
func (u *FileUsecase) UploadFile(ctx context.Context, kbID string, file *multipart.FileHeader) (string, error) {
|
|
src, err := file.Open()
|
|
if err != nil {
|
|
return "", fmt.Errorf("failed to open file: %w", err)
|
|
}
|
|
defer src.Close()
|
|
|
|
ext := strings.ToLower(filepath.Ext(file.Filename))
|
|
filename := fmt.Sprintf("%s/%s%s", kbID, uuid.New().String(), ext)
|
|
|
|
size := file.Size
|
|
|
|
contentType := file.Header.Get("Content-Type")
|
|
if contentType == "" {
|
|
contentType = mime.TypeByExtension(ext)
|
|
}
|
|
|
|
resp, err := u.s3Client.PutObject(
|
|
ctx,
|
|
domain.Bucket,
|
|
filename,
|
|
src,
|
|
size,
|
|
minio.PutObjectOptions{
|
|
ContentType: contentType,
|
|
UserMetadata: map[string]string{
|
|
"originalname": file.Filename,
|
|
},
|
|
},
|
|
)
|
|
if err != nil {
|
|
return "", fmt.Errorf("upload failed: %w", err)
|
|
}
|
|
|
|
return resp.Key, nil
|
|
}
|
|
|
|
func (u *FileUsecase) UploadFileFromBytes(ctx context.Context, kbID string, filename string, fileBytes []byte) (string, error) {
|
|
// Create a reader from the byte slice
|
|
reader := bytes.NewReader(fileBytes)
|
|
|
|
ext := strings.ToLower(filepath.Ext(filename))
|
|
s3Filename := fmt.Sprintf("%s/%s%s", kbID, uuid.New().String(), ext)
|
|
|
|
size := int64(len(fileBytes))
|
|
|
|
contentType := mime.TypeByExtension(ext)
|
|
if contentType == "" {
|
|
// Fallback content type if extension not recognized
|
|
contentType = "application/octet-stream"
|
|
}
|
|
|
|
resp, err := u.s3Client.PutObject(
|
|
ctx,
|
|
domain.Bucket,
|
|
s3Filename,
|
|
reader,
|
|
size,
|
|
minio.PutObjectOptions{
|
|
ContentType: contentType,
|
|
UserMetadata: map[string]string{
|
|
"originalname": filename,
|
|
},
|
|
},
|
|
)
|
|
if err != nil {
|
|
return "", fmt.Errorf("upload failed: %w", err)
|
|
}
|
|
|
|
return resp.Key, nil
|
|
}
|
|
|
|
func (u *FileUsecase) UploadFileFromReader(
|
|
ctx context.Context,
|
|
kbID string,
|
|
filename string,
|
|
reader io.Reader,
|
|
size int64, // 必须提供对象大小
|
|
) (string, error) {
|
|
// 生成唯一文件名
|
|
ext := strings.ToLower(filepath.Ext(filename))
|
|
s3Filename := fmt.Sprintf("%s/%s%s", kbID, uuid.New().String(), ext)
|
|
|
|
// 获取内容类型
|
|
contentType := mime.TypeByExtension(ext)
|
|
if contentType == "" {
|
|
contentType = "application/octet-stream" // 默认类型
|
|
}
|
|
|
|
// 上传到 S3
|
|
_, err := u.s3Client.PutObject(
|
|
ctx,
|
|
domain.Bucket,
|
|
s3Filename,
|
|
reader,
|
|
size, // 必须提供对象大小
|
|
minio.PutObjectOptions{
|
|
ContentType: contentType,
|
|
UserMetadata: map[string]string{
|
|
"originalname": filename,
|
|
},
|
|
},
|
|
)
|
|
if err != nil {
|
|
return "", fmt.Errorf("S3 upload failed: %w", err)
|
|
}
|
|
|
|
return s3Filename, nil
|
|
}
|
|
|
|
func (u *FileUsecase) AnyDocUploadFile(ctx context.Context, file *multipart.FileHeader, path string) (string, error) {
|
|
src, err := file.Open()
|
|
if err != nil {
|
|
return "", fmt.Errorf("failed to open file: %w", err)
|
|
}
|
|
defer src.Close()
|
|
|
|
ext := strings.ToLower(filepath.Ext(file.Filename))
|
|
|
|
size := file.Size
|
|
|
|
contentType := file.Header.Get("Content-Type")
|
|
if contentType == "" {
|
|
contentType = mime.TypeByExtension(ext)
|
|
}
|
|
|
|
resp, err := u.s3Client.PutObject(
|
|
ctx,
|
|
domain.Bucket,
|
|
path,
|
|
src,
|
|
size,
|
|
minio.PutObjectOptions{
|
|
ContentType: contentType,
|
|
UserMetadata: map[string]string{
|
|
"originalname": file.Filename,
|
|
},
|
|
},
|
|
)
|
|
if err != nil {
|
|
return "", fmt.Errorf("upload failed: %w", err)
|
|
}
|
|
|
|
return resp.Key, nil
|
|
}
|