Files
soul-yongping/soul-api/internal/handler/oss.go
卡若 76965adb23 chore: 清理敏感与开发文档,仅同步代码
- 永久忽略并从仓库移除 开发文档/
- 移除并忽略 .env 与小程序私有配置
- 同步小程序/管理端/API与脚本改动

Made-with: Cursor
2026-03-17 17:50:12 +08:00

149 lines
4.1 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 handler
import (
"encoding/json"
"fmt"
"io"
"mime/multipart"
"strings"
"time"
"github.com/aliyun/aliyun-oss-go-sdk/oss"
"soul-api/internal/database"
"soul-api/internal/model"
)
type ossConfigCache struct {
Endpoint string `json:"endpoint"`
AccessKeyID string `json:"accessKeyId"`
AccessKeySecret string `json:"accessKeySecret"`
Bucket string `json:"bucket"`
Region string `json:"region"`
}
func getOssConfig() *ossConfigCache {
db := database.DB()
var row model.SystemConfig
if err := db.Where("config_key = ?", "oss_config").First(&row).Error; err != nil {
return nil
}
var cfg ossConfigCache
if err := json.Unmarshal(row.ConfigValue, &cfg); err != nil {
return nil
}
if cfg.Endpoint == "" || cfg.AccessKeyID == "" || cfg.AccessKeySecret == "" || cfg.Bucket == "" {
return nil
}
return &cfg
}
func ossUploadFile(file multipart.File, folder, filename string) (string, error) {
cfg := getOssConfig()
if cfg == nil {
return "", fmt.Errorf("OSS 未配置")
}
endpoint := cfg.Endpoint
if !strings.HasPrefix(endpoint, "http://") && !strings.HasPrefix(endpoint, "https://") {
endpoint = "https://" + endpoint
}
client, err := oss.New(endpoint, cfg.AccessKeyID, cfg.AccessKeySecret)
if err != nil {
return "", fmt.Errorf("创建 OSS 客户端失败: %w", err)
}
bucket, err := client.Bucket(cfg.Bucket)
if err != nil {
return "", fmt.Errorf("获取 Bucket 失败: %w", err)
}
objectKey := fmt.Sprintf("%s/%s/%s", folder, time.Now().Format("2006-01"), filename)
data, err := io.ReadAll(file)
if err != nil {
return "", fmt.Errorf("读取文件失败: %w", err)
}
err = bucket.PutObject(objectKey, strings.NewReader(string(data)))
if err != nil {
return "", fmt.Errorf("上传 OSS 失败: %w", err)
}
signedURL, err := bucket.SignURL(objectKey, oss.HTTPGet, 3600*24*365*10)
if err != nil {
host := cfg.Bucket + "." + cfg.Endpoint
if !strings.HasPrefix(cfg.Endpoint, "http://") && !strings.HasPrefix(cfg.Endpoint, "https://") {
host = cfg.Bucket + "." + cfg.Endpoint
} else {
host = strings.Replace(cfg.Endpoint, "://", "://"+cfg.Bucket+".", 1)
}
if !strings.HasPrefix(host, "http://") && !strings.HasPrefix(host, "https://") {
host = "https://" + host
}
return host + "/" + objectKey, nil
}
return normalizeOSSUrl(signedURL), nil
}
// normalizeOSSUrl 修复 OSS SDK 可能返回的缺少冒号的 URL如 "https//..." → "https://..."
func normalizeOSSUrl(u string) string {
if strings.HasPrefix(u, "https//") {
return "https://" + u[7:]
}
if strings.HasPrefix(u, "http//") {
return "http://" + u[6:]
}
return u
}
func ossUploadBytes(data []byte, folder, filename, contentType string) (string, error) {
cfg := getOssConfig()
if cfg == nil {
return "", fmt.Errorf("OSS 未配置")
}
endpoint := cfg.Endpoint
if !strings.HasPrefix(endpoint, "http://") && !strings.HasPrefix(endpoint, "https://") {
endpoint = "https://" + endpoint
}
client, err := oss.New(endpoint, cfg.AccessKeyID, cfg.AccessKeySecret)
if err != nil {
return "", fmt.Errorf("创建 OSS 客户端失败: %w", err)
}
bucket, err := client.Bucket(cfg.Bucket)
if err != nil {
return "", fmt.Errorf("获取 Bucket 失败: %w", err)
}
objectKey := fmt.Sprintf("%s/%s/%s", folder, time.Now().Format("2006-01"), filename)
var opts []oss.Option
if contentType != "" {
opts = append(opts, oss.ContentType(contentType))
}
err = bucket.PutObject(objectKey, strings.NewReader(string(data)), opts...)
if err != nil {
return "", fmt.Errorf("上传 OSS 失败: %w", err)
}
signedURL, err := bucket.SignURL(objectKey, oss.HTTPGet, 3600*24*365*10)
if err != nil {
host := cfg.Bucket + "." + cfg.Endpoint
if !strings.HasPrefix(cfg.Endpoint, "http://") && !strings.HasPrefix(cfg.Endpoint, "https://") {
host = cfg.Bucket + "." + cfg.Endpoint
} else {
host = strings.Replace(cfg.Endpoint, "://", "://"+cfg.Bucket+".", 1)
}
if !strings.HasPrefix(host, "http://") && !strings.HasPrefix(host, "https://") {
host = "https://" + host
}
return host + "/" + objectKey, nil
}
return normalizeOSSUrl(signedURL), nil
}