package aliyun import ( "crypto/hmac" "crypto/sha1" "encoding/base64" "encoding/xml" "fmt" "io" "net/http" "time" "u-desk/internal/oss" ) // ListBuckets 列出所有存储桶 func ListBuckets(accessKeyID, accessKeySecret, endpoint string) ([]oss.BucketEntry, error) { if endpoint == "" { endpoint = "oss-cn-hangzhou.aliyuncs.com" } url := "https://" + endpoint + "/" req, _ := http.NewRequest("GET", url, nil) date := time.Now().UTC().Format("Mon, 02 Jan 2006 15:04:05 GMT") req.Header.Set("Date", date) stringToSign := "GET\n\n\n" + date + "\n/" signature := sign(accessKeySecret, stringToSign) req.Header.Set("Authorization", "OSS "+accessKeyID+":"+signature) resp, err := http.DefaultClient.Do(req) if err != nil { return nil, fmt.Errorf("列举存储桶失败: %w", err) } defer resp.Body.Close() if resp.StatusCode != http.StatusOK { body, _ := io.ReadAll(resp.Body) return nil, fmt.Errorf("列举存储桶失败: HTTP %d: %s", resp.StatusCode, string(body)) } var result listAllMyBucketsResult if err := xml.NewDecoder(resp.Body).Decode(&result); err != nil { return nil, fmt.Errorf("解析存储桶列表失败: %w", err) } entries := make([]oss.BucketEntry, len(result.Buckets.Bucket)) for i, b := range result.Buckets.Bucket { entries[i] = oss.BucketEntry{ Name: b.Name, Region: b.Location, } } return entries, nil } func sign(secretKey, data string) string { mac := hmac.New(sha1.New, []byte(secretKey)) mac.Write([]byte(data)) return base64.StdEncoding.EncodeToString(mac.Sum(nil)) } type listAllMyBucketsResult struct { XMLName xml.Name `xml:"ListAllMyBucketsResult"` Buckets struct { Bucket []bucketEntryXML `xml:"Bucket"` } `xml:"Buckets"` } type bucketEntryXML struct { Name string `xml:"Name"` Location string `xml:"Location"` }