Private
Public Access
1
0
Files
u-desk/internal/oss/aliyun/bucket.go

74 lines
1.8 KiB
Go

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"`
}