簡體   English   中英

谷歌雲平台 presignURL 使用 Go

[英]Google Cloud Platform presignURL using Go

嘗試將圖片上傳到谷歌雲平台,我總是得到相同的錯誤"<?xml version='1.0' encoding='UTF-8'?><Error><Code>SignatureDoesNotMatch</Code><Message>The request signature we calculated does not match the signature you provided. Check your Google secret key and signing method.</Message><StringToSign>GOOG4-RSA-SHA256 20.................951Z"

我確實向存儲桶添加了一個服務帳戶,角色為 Storage Admin 和 Storage Object Admin,如您在圖片上看到的

在此處輸入圖像描述

我已經生成了一個密鑰(用於服務帳戶)並將其下載為 .json 文件,然后使用以下代碼生成一個 presignURL:

// key is the downloaded .json key file from the GCP service-account 
// the return string is the presignedURL 
func getPresignedURL(path, key string) (string, error) {
    sakeyFile := filepath.Join(path, key)

    saKey, err := ioutil.ReadFile(sakeyFile)
    if err != nil {
        log.Fatalln(err)
    }

    cfg, err := google.JWTConfigFromJSON(saKey)
    if err != nil {
        log.Fatalln(err)
    }

    bucket := "mybucket"

    ctx := context.Background()
    client, err := storage.NewClient(ctx)
    if err != nil {
        return "", fmt.Errorf("storage.NewClient: %v", err)
    }
    defer client.Close()

    opts := &storage.SignedURLOptions{
        Scheme: storage.SigningSchemeV4,
        Method: "PUT",
        Headers: []string{
            // "Content-Type:application/octet-stream",
            "Content-Type:multipart/form-data",
        },
        Expires:        time.Now().Add(15 * time.Minute),
        GoogleAccessID: cfg.Email,
        PrivateKey:     cfg.PrivateKey,
    }

    u, err := client.Bucket(bucket).SignedURL("mypic.jpeg", opts)
    if err != nil {
        return "", fmt.Errorf("Bucket(%q).SignedURL: %v", bucket, err)
    }

    return u, nil 
}

presignedURL 看起來不錯,如下所示:

https://storage.googleapis.com/djedjepicbucket/mypic.jpeg?X-Goog-Algorithm=GOOG4-RSA-SHA256&X-Goog-Credential=djedje%40picstorage-363707.iam.gserviceaccount.com%2F20220926%2Fauto%2Fstorage%2Fgoog4_request&X-Goog-Date=20220926T081951Z&X-Goog-Expires=899&X-Goog Signature=3f330715d7a38ea08f99134a16f464fb............5ad800a7665dfb1440034ab1f5ab045252336&X-Goog-SignedHeaders=content-type%3Bhost

然后我從磁盤讀取文件(圖片)並使用 presignURL 上傳

// the uri is the presignedURL
func newfileUploadRequest(uri string, params map[string]string, paramName, path string) (*http.Request, error) {
    file, err := os.Open(path)
    if err != nil {
        return nil, err
    }
    defer file.Close()

    body := &bytes.Buffer{}
    writer := multipart.NewWriter(body)
    part, err := writer.CreateFormFile(paramName, filepath.Base(path))
    if err != nil {
        return nil, err
    }
    _, err = io.Copy(part, file)

    for key, val := range params {
        _ = writer.WriteField(key, val)
    }
    err = writer.Close()
    if err != nil {
        return nil, err
    }

    req, err := http.NewRequest("PUT", uri, body)
    req.Header.Set("Content-Type", writer.FormDataContentType())
    return req, err
}

然后我執行請求

// the previous func
request, err := newfileUploadRequest(purl, extraParams, "picture", filepath.Join(path, "download.jpeg"))
if err != nil {
    log.Fatal(err)
}

client := &http.Client{}
resp, err := client.Do(request)
if err != nil {
    log.Fatal(err)
} else {
    body := &bytes.Buffer{}
    _, err := body.ReadFrom(resp.Body)
    if err != nil {
        log.Fatal(err)
    }
    resp.Body.Close()
    fmt.Println(resp.StatusCode)
    fmt.Println(resp.Header)
    fmt.Println(body)
}

不幸的是,我總是得到同樣的錯誤

403
map[Alt-Svc:[h3=":443"; ma=2592000,h3-29=":443"; ma=2592000,h3-Q050=":443"; ma=2592000,h3-Q046=":443"; ma=2592000,h3-Q043=":443"; ma=2592000,quic=":443"; ma=2592000; v="46,43"] Content-Length:[884] Content-Type:[application/xml; charset=UTF-8] Date:[Mon, 26 Sep 2022 08:22:19 GMT] Server:[UploadServer] X-Guploader-Uploadid:[ADPyc......................ECL_4W]]
<?xml version='1.0' encoding='UTF-8'?><Error><Code>SignatureDoesNotMatch</Code><Message>The request signature we calculated does not match the signature you provided. Check your Google secret key and signing method.</Message><StringToSign>GOOG4-RSA-SHA256
20220926T081951Z
20220926/auto/storage/goog4_request
c5f36838af4......................8ffb56329c1eb27f</StringToSign><CanonicalRequest>PUT
/djedjepicbucket/mypic.jpeg
X-Goog-Algorithm=GOOG4-RSA-SHA256&amp;X-Goog-Credential=djedje%40picstorage-363707.iam.gserviceaccount.com%2F20220926%2Fauto%2Fstorage%2Fgoog4_request&amp;X-Goog-Date=20220926T081951Z&amp;X-Goog-Expires=899&amp;X-Goog-SignedHeaders=content-type%3Bhost
content-type:multipart/form-data; boundary=5be13cc........................dd6aef6823
host:storage.googleapis.com

content-type;host
UNSIGNED-PAYLOAD</CanonicalRequest></Error>

實際上我也嘗試了許多其他方法,但我基本上總是得到這個(或多或少)同樣的錯誤,有人知道我忘記了什么(我現在已經堅持了 2 天......)? 謝謝

找到答案,在getPresignedURL()newfileUploadRequest()函數中,Header 必須設置為"Content-Type:application/octet-stream" ,然后圖片上傳沒有問題。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM