使用node.js为Google云端存储创建已签名的网址,以便从浏览器直接上传

时间:2016-10-16 16:07:42

标签: javascript node.js google-cloud-storage

实际测试用例代码: https://github.com/HenrikJoreteg/google-cloud-signedurl-test-case

我尝试为我的API添加功能,以返回已签名的网址,以便从客户端直接上传到Google云端存储。

Serverside,我正在使用gcloud SDK:

const gcloud = require('gcloud')

const gcs = gcloud.storage({
  projectId: 'my project',
  keyFilename: __dirname + '/path/to/JSON/file.json'
})
const bucket = gcs.bucket('bucket-name')

bucket.file('IMG_2540.png').getSignedUrl({
 action: 'write',
 expires: Date.now() + 60000
}, (error, signedUrl) => {
  if (error == null) {
    console.log(signedUrl)
  }
})

然后在浏览器中我找到了<input type='file'/>我选择了一个文件,然后我尝试将其发布到我的服务器端脚本生成的URL中,如下所示: / p>

function upload(blobOrFile, url) {
  var xhr = new XMLHttpRequest();
  xhr.open('PUT', url, true);
  xhr.onload = function(e) {
    console.log('DONE!')
  };
  xhr.upload.onprogress = function(e) {
    if (e.lengthComputable) {
      console.log((e.loaded / e.total) * 100)
    }
  };

  xhr.send(blobOrFile);
}

// grab the `File` object dropped (which incidentally
// matches the file name used when generating the signed URL 
upload($('[name=file]').files[0], 'URL GENERATED FROM SERVER-SIDE SCRIPT HERE');

会发生什么?

回应是:

<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>PUT

image/png
1476631908
/bucket-name/IMG_2540.png</StringToSign>
</Error>

我重新下载了JSON密钥文件,以确保它是最新的并具有该存储桶的适当权限,并且在生成签名网址时我不会收到任何错误或任何内容。

客户端代码似乎正确启动上传(我看到进度更新已注销)然后我收到403错误。文件名匹配,内容类型似乎与预期值匹配,到期似乎合理。

官方SDK生成了URL,所以看起来好像没问题。

我被困住了,任何帮助都表示赞赏。

1 个答案:

答案 0 :(得分:4)

正如Philip Roberts所指出的那样,在我的github repo中包含@LatentFlip的情况下,在签名中添加了一个内容类型来处理它。

https://github.com/HenrikJoreteg/google-cloud-signedurl-test-case/pull/1/commits/84290918e7b82dd8c1f22ffcd2c7cdc06b08d334

此外,听起来像谷歌人会更新文档/错误更有帮助:https://github.com/GoogleCloudPlatform/google-cloud-node/issues/1695