| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154 |
- package controllers
- import (
- "crypto/hmac"
- "crypto/sha256"
- "encoding/base64"
- "encoding/hex"
- "encoding/json"
- "fmt"
- "shudao-chat-go/utils"
- "strconv"
- "time"
- "github.com/beego/beego/v2/server/web"
- )
- type OssController struct {
- web.Controller
- }
- // S3配置信息
- var accessKeyId string = "fnyfi2f368pbic74d8ll"
- var accessKeySecret string = "jgqwk7sirqlz2602x2k7yx2eor0vii19wah6ywlv"
- var bucket string = "gdsc-ai-aqzs"
- var endpoint string = "172.16.17.52:8060"
- var region string = "raoxi" // S3区域,可根据实际情况调整
- // S3服务地址 - 标准S3格式
- var host string = "http://" + endpoint + "/" + bucket
- // 用户上传文件时指定的前缀
- var upload_dir string = "uploads/"
- var expire_time int64 = 1800 // 30分钟
- // S3策略文档结构
- type S3PolicyDocument struct {
- Expiration string `json:"expiration"`
- Conditions []interface{} `json:"conditions"`
- }
- // S3响应结构
- type S3PolicyToken struct {
- URL string `json:"url"`
- Fields map[string]string `json:"fields"`
- Expire int64 `json:"expire"`
- StatusCode int `json:"statusCode"`
- }
- // 生成AWS4签名
- func generateAWS4Signature(secretKey, dateStamp, region, stringToSign string) string {
- kDate := hmacSHA256([]byte("AWS4"+secretKey), dateStamp)
- kRegion := hmacSHA256(kDate, region)
- kService := hmacSHA256(kRegion, "s3")
- kSigning := hmacSHA256(kService, "aws4_request")
- signature := hmacSHA256(kSigning, stringToSign)
- return hex.EncodeToString(signature)
- }
- // HMAC-SHA256计算
- func hmacSHA256(key []byte, data string) []byte {
- mac := hmac.New(sha256.New, key)
- mac.Write([]byte(data))
- return mac.Sum(nil)
- }
- func (c *OssController) Upload() {
- // 设置CORS头
- c.Ctx.ResponseWriter.Header().Set("Access-Control-Allow-Origin", "*")
- c.Ctx.ResponseWriter.Header().Set("Access-Control-Allow-Methods", "GET, POST, OPTIONS")
- c.Ctx.ResponseWriter.Header().Set("Access-Control-Allow-Headers", "Content-Type")
- // 处理OPTIONS预检请求
- if c.Ctx.Request.Method == "OPTIONS" {
- c.Ctx.ResponseWriter.WriteHeader(200)
- return
- }
- // 从token中获取用户信息
- userInfo, err := utils.GetUserInfoFromContext(c.Ctx.Input.GetData("userInfo"))
- if err != nil {
- c.Data["json"] = map[string]interface{}{
- "statusCode": 401,
- "error": "获取用户信息失败: " + err.Error(),
- }
- c.ServeJSON()
- return
- }
- user_id := int(userInfo.ID)
- if user_id == 0 {
- user_id = 1
- }
- // 生成时间相关字符串
- now := time.Now().UTC()
- expire_end := now.Unix() + expire_time
- dateStamp := now.Format("20060102")
- amzDate := now.Format("20060102T150405Z")
- expiration := now.Add(time.Duration(expire_time) * time.Second).Format("2006-01-02T15:04:05.000Z")
- // 生成credential
- credential := fmt.Sprintf("%s/%s/%s/s3/aws4_request", accessKeyId, dateStamp, region)
- // 生成上传目录
- uploadDir := upload_dir + now.Format("01") + now.Format("02") + "/" + strconv.Itoa(user_id) + "/"
- // 创建S3策略文档
- policy := S3PolicyDocument{
- Expiration: expiration,
- Conditions: []interface{}{
- map[string]string{"bucket": bucket},
- []interface{}{"starts-with", "$key", uploadDir},
- map[string]string{"x-amz-algorithm": "AWS4-HMAC-SHA256"},
- map[string]string{"x-amz-credential": credential},
- map[string]string{"x-amz-date": amzDate},
- []interface{}{"content-length-range", "0", "104857600"}, // 最大100MB
- },
- }
- // 将策略文档转换为JSON并进行Base64编码
- policyJSON, err := json.Marshal(policy)
- if err != nil {
- c.Data["json"] = map[string]interface{}{
- "statusCode": 500,
- "error": "Failed to create policy",
- }
- c.ServeJSON()
- return
- }
- policyBase64 := base64.StdEncoding.EncodeToString(policyJSON)
- // 生成AWS4签名
- signature := generateAWS4Signature(accessKeySecret, dateStamp, region, policyBase64)
- // 构建表单字段
- fields := map[string]string{
- "key": uploadDir + "${filename}",
- "policy": policyBase64,
- "x-amz-algorithm": "AWS4-HMAC-SHA256",
- "x-amz-credential": credential,
- "x-amz-date": amzDate,
- "x-amz-signature": signature,
- }
- // 构建响应
- var policyToken S3PolicyToken
- policyToken.StatusCode = 200
- policyToken.URL = host
- policyToken.Fields = fields
- policyToken.Expire = expire_end
- c.Data["json"] = policyToken
- c.ServeJSON()
- }
|