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() }