Files
tamabox/internal/storage/oss.go
T
2026-09-08 10:10:44 +08:00

67 lines
1.8 KiB
Go

// Copyright 2022 E99p1ant. All rights reserved.
// Use of this source code is governed by a MIT-style
// license that can be found in the LICENSE file.
package storage
import (
"fmt"
"io"
"mime/multipart"
"time"
"github.com/pkg/errors"
"github.com/thanhpk/randstr"
"github.com/wuhan005/gadget"
"github.com/tamakyi/TamaBox/internal/conf"
)
// UploadPictureToOSS upload user's avatar or background image to OSS.
// It returns the uploaded asset URL.
func UploadPictureToOSS(file multipart.File, _ *multipart.FileHeader) (string, error) {
// 读取文件头,校验是否为图片
header := make([]byte, 512)
n, err := file.Read(header)
if err != nil && err != io.EOF {
return "", errors.Wrap(err, "read file header")
}
if n == 0 {
return "", errors.New("empty file")
}
if !isSupportedImage(header[:n]) {
return "", errors.New("不支持的文件格式,仅允许 JPEG、PNG、GIF、WebP 图片")
}
// 重置文件指针
if _, err := file.Seek(0, io.SeekStart); err != nil {
return "", errors.Wrap(err, "seek file")
}
// 获取共享 OSS bucket
bucket, err := GetOSSBucket()
if err != nil {
return "", errors.Wrap(err, "get OSS bucket")
}
now := time.Now()
year := now.Year()
month := int(now.Month())
day := now.Day()
key := fmt.Sprintf("%s%d/%02d/%02d/%s", PictureKeyPrefix, year, month, day, randstr.Hex(15))
if err := gadget.Retry(5, func() error {
if err := bucket.PutObject(key, file); err != nil {
return errors.Wrap(err, "put object")
}
return nil
}); err != nil {
return "", errors.Wrap(err, "retry 5 times")
}
if conf.Upload.AliyunBucketCDNHost != "" {
return fmt.Sprintf("https://%s/%s", conf.Upload.AliyunBucketCDNHost, key), nil
}
return fmt.Sprintf("https://%s.%s/%s", conf.Upload.AliyunBucket, conf.Upload.AliyunEndpoint, key), nil
}