繁体   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