Files
epic-go/internal/util/oss.go
hu xiaotong 8657bc4eea i18n翻译
2025-07-14 17:31:48 +08:00

99 lines
2.8 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

package util
import (
"context"
"epic/internal/consts"
"fmt"
"io"
"net/http"
"os"
"path/filepath"
"time"
"github.com/aws/aws-sdk-go-v2/aws"
"github.com/aws/aws-sdk-go-v2/config"
"github.com/aws/aws-sdk-go-v2/credentials"
"github.com/aws/aws-sdk-go-v2/service/s3"
)
// DownloadAndUploadToOSS 下载网络图片并上传到OSS返回OSS路径
// imageUrl: 网络图片完整URL
// 返回: OSS上的图片URL或错误
func DownloadAndUploadToOSS(ctx context.Context, imageUrl string) (string, error) {
// 1. 下载 imageUrl 到本地临时文件
resp, err := http.Get(imageUrl)
if err != nil {
return "", fmt.Errorf("failed to download image: %w", err)
}
defer resp.Body.Close()
if resp.StatusCode != http.StatusOK {
return "", fmt.Errorf("failed to download image: status %d", resp.StatusCode)
}
tmpFile, err := os.CreateTemp("", "ossimg-*.tmp")
if err != nil {
return "", fmt.Errorf("failed to create temp file: %w", err)
}
tmpFilePath := tmpFile.Name()
defer func() {
tmpFile.Close()
os.Remove(tmpFilePath)
}()
_, err = io.Copy(tmpFile, resp.Body)
if err != nil {
return "", fmt.Errorf("failed to save image to temp file: %w", err)
}
// 2. 上传临时文件到OSS获取OSS路径
accessKey := consts.S3AccessKey
secretKey := consts.S3SecretKey
bucket := consts.S3Bucket
region := consts.S3Region
endpoint := consts.S3Endpoint
if accessKey == "" || secretKey == "" || bucket == "" || endpoint == "" {
return "", fmt.Errorf("missing S3 credentials or bucket info in consts")
}
customResolver := aws.EndpointResolverWithOptionsFunc(func(service, region string, options ...interface{}) (aws.Endpoint, error) {
if service == s3.ServiceID {
return aws.Endpoint{URL: endpoint}, nil
}
return aws.Endpoint{}, fmt.Errorf("unknown service requested")
})
customProvider := credentials.NewStaticCredentialsProvider(accessKey, secretKey, "")
cfg, err := config.LoadDefaultConfig(ctx,
config.WithCredentialsProvider(customProvider),
config.WithEndpointResolverWithOptions(customResolver),
)
if err != nil {
return "", fmt.Errorf("failed to load S3 config: %w", err)
}
cfg.Region = region
s3Client := s3.NewFromConfig(cfg)
// 生成唯一的 object key
fileName := filepath.Base(tmpFilePath)
objectKey := fmt.Sprintf("images/%d_%s", time.Now().UnixNano(), fileName)
tmpFile.Seek(0, io.SeekStart)
_, err = tmpFile.Stat()
if err != nil {
return "", fmt.Errorf("failed to stat temp file: %w", err)
}
// 上传
_, err = s3Client.PutObject(ctx, &s3.PutObjectInput{
Bucket: aws.String(bucket),
Key: aws.String(objectKey),
Body: tmpFile,
})
if err != nil {
return "", fmt.Errorf("failed to upload to S3: %w", err)
}
// 4. 返回OSS路径拼接URL
ossUrl := fmt.Sprintf("%s/%s/%s", endpoint, bucket, objectKey)
return ossUrl, nil
}