feat():learning后台管理项目初始化
This commit is contained in:
100
internal/oss/s3.go
Normal file
100
internal/oss/s3.go
Normal file
@@ -0,0 +1,100 @@
|
||||
package oss
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
"fmt"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"goalfymax-admin/internal/config"
|
||||
|
||||
"github.com/aws/aws-sdk-go-v2/aws"
|
||||
"github.com/aws/aws-sdk-go-v2/credentials"
|
||||
"github.com/aws/aws-sdk-go-v2/service/s3"
|
||||
)
|
||||
|
||||
type s3Client struct {
|
||||
client *s3.Client
|
||||
presign *s3.PresignClient
|
||||
cfg config.OssConfig
|
||||
}
|
||||
|
||||
var (
|
||||
clientOnce sync.Once
|
||||
c *s3Client
|
||||
)
|
||||
|
||||
func initClient() error {
|
||||
var initErr error
|
||||
clientOnce.Do(func() {
|
||||
cfg := config.GetConfig().Oss
|
||||
if cfg.Region == "" || cfg.Bucket == "" || cfg.AccessKeyID == "" || cfg.AccessKeySecret == "" {
|
||||
initErr = fmt.Errorf("OSS未配置: region/bucket/ak/sk 不能为空")
|
||||
return
|
||||
}
|
||||
|
||||
awsCfg := aws.Config{
|
||||
Region: cfg.Region,
|
||||
Credentials: credentials.NewStaticCredentialsProvider(cfg.AccessKeyID, cfg.AccessKeySecret, ""),
|
||||
}
|
||||
|
||||
s3c := s3.NewFromConfig(awsCfg)
|
||||
c = &s3Client{
|
||||
client: s3c,
|
||||
presign: s3.NewPresignClient(s3c),
|
||||
cfg: cfg,
|
||||
}
|
||||
})
|
||||
return initErr
|
||||
}
|
||||
|
||||
// GetPresignedGetURL 生成S3对象的预签名下载URL
|
||||
func GetPresignedGetURL(ctx context.Context, key string) (string, error) {
|
||||
if err := initClient(); err != nil {
|
||||
return "", err
|
||||
}
|
||||
expire := c.cfg.PresignUrlExpire
|
||||
if expire <= 0 {
|
||||
expire = 10 * time.Minute
|
||||
}
|
||||
req, err := c.presign.PresignGetObject(ctx, &s3.GetObjectInput{
|
||||
Bucket: aws.String(c.cfg.Bucket),
|
||||
Key: aws.String(key),
|
||||
}, func(po *s3.PresignOptions) {
|
||||
po.Expires = expire
|
||||
})
|
||||
if err != nil {
|
||||
return "", fmt.Errorf("生成预签名URL失败: %w", err)
|
||||
}
|
||||
return req.URL, nil
|
||||
}
|
||||
|
||||
// DownloadFileContent 从S3下载文件内容和MIME类型
|
||||
func DownloadFileContent(ctx context.Context, key string) ([]byte, string, error) {
|
||||
if err := initClient(); err != nil {
|
||||
return nil, "", err
|
||||
}
|
||||
|
||||
resp, err := c.client.GetObject(ctx, &s3.GetObjectInput{
|
||||
Bucket: aws.String(c.cfg.Bucket),
|
||||
Key: aws.String(key),
|
||||
})
|
||||
if err != nil {
|
||||
return nil, "", fmt.Errorf("从S3下载文件失败: %w", err)
|
||||
}
|
||||
defer resp.Body.Close()
|
||||
|
||||
buf := new(bytes.Buffer)
|
||||
_, err = buf.ReadFrom(resp.Body)
|
||||
if err != nil {
|
||||
return nil, "", fmt.Errorf("读取文件内容失败: %w", err)
|
||||
}
|
||||
|
||||
mimeType := "application/octet-stream" // 默认MIME类型
|
||||
if resp.ContentType != nil && *resp.ContentType != "" {
|
||||
mimeType = *resp.ContentType
|
||||
}
|
||||
|
||||
return buf.Bytes(), mimeType, nil
|
||||
}
|
||||
Reference in New Issue
Block a user