如何使用签名的 URL 将文件上传到谷歌云存储桶

Posted

技术标签:

【中文标题】如何使用签名的 URL 将文件上传到谷歌云存储桶【英文标题】:How to upload file to google cloud bucket using signedUrl 【发布时间】:2019-09-09 17:02:33 【问题描述】:

我正在开发一个 Angular 应用程序,以显示谷歌云存储桶的内容。后面我在nodeJS中使用google cloud函数

正如他们在上传文件的文档中提到的,我创建了一个函数来生成签名的 url,但是当我使用签名的 url 发送文件时,我在浏览器中遇到了 cors 错误

我用邮递员测试过,它上传一个空文件

这是我的 lambda 函数:

// Imports the Google Cloud client library
const Storage = require('@google-cloud/storage');

// Creates a client
const storage = new Storage();

exports.generateSignedUrl = (req, res) => 
// generate signed url to use for file upload

const filename = req.query.fileName;
console.log('filename ', filename);

const filetype = req.query.fileType;
console.log('filetype ', filetype);

const bucketName = 'nx-terega-omega';

res.set('Access-Control-Allow-Origin', "*");
res.set('Access-Control-Allow-Headers', "Origin, X-Requested-With, 
Content-Type, Accept, Authorization");

if (req.query.fileName !== null && req.query.fileName !== undefined
  && req.query.fileType !== null && req.query.fileType !== undefined) 

generateV4UploadSignedUrl(bucketName, filename).then(function (value) 

  console.log('File Url response ', value);
  res.status(200).send(JSON.stringify('url': value));
).catch(error => 
  res.status(404).send('Error while generating signed url');
);
 else 
res.status(500).send('Filename not found');

;

async function generateV4UploadSignedUrl(bucketName, filename, filetype) 
// [START storage_generate_upload_signed_url_v4]

// These options will allow temporary uploading of the file with outgoing
// Content-Type: application/octet-stream header.
const options = 
version: 'v4',
action: 'write',
expires: Date.now() + 15 * 60 * 1000, // 15 minutes
contentType: filetype,
;

// Get a v4 signed URL for uploading file
const [url] = await storage
.bucket(bucketName)
.file(filename)
.getSignedUrl(options);

console.log('Generated PUT signed URL:');
console.log(url);
console.log('You can use this URL with any user agent, for example:');
console.log("curl -X PUT -H 'Content-Type: application/octet-stream' " +`--upload-file my-file '$url'`);

return url;
// [END storage_generate_upload_signed_url_v4]

当我收到签名的 url 时,我将我的文件发送到其中,但它返回了

No 'Access-Control-Allow-Origin' header is present on the requested resource.

【问题讨论】:

【参考方案1】:

Brandon Yarbrough 回复中所述,我必须在 Google Cloud 中配置 cors。我的配置中遗漏了一些东西

[
 
  "origin": ["http://example.appspot.com"],
  "responseHeader": ["*"],
  "method": ["GET", "HEAD", "DELETE", "PUT"],
  "maxAgeSeconds": 3600
 
]

您应该将PUT 包含在method 中,并将* 放入responseHeader,因为Content-Type 是不够的

【讨论】:

【参考方案2】:

签名 URL 使用 GCS 的 XML API。该 API 允许跨域请求,但默认情况下不启用它。您需要为存储桶指定 CORS 策略。

例如,您可以创建如下所示的 CORS 策略(假设这是一个名为 policy.json 的文件):

[
    
      "origin": ["http://example.appspot.com"],
      "responseHeader": ["Content-Type"],
      "method": ["GET", "HEAD", "DELETE"],
      "maxAgeSeconds": 3600
    
]

CORS 政策文档的完整描述在这里:https://cloud.google.com/storage/docs/xml-api/put-bucket-cors#request_body_elements

现在让我们将该策略应用于存储桶:

gsutil cors set policy.json gs://my-bucket-name

文档中有更多关于在存储桶上启用 CORS 的说明:https://cloud.google.com/storage/docs/configuring-cors

【讨论】:

不起作用,返回has been blocked by CORS policy: Response to preflight request doesn't pass access control check: No 'Access-Control-Allow-Origin' header is present on the requested resource. 您的 CORS 策略是否包含 OPTIONS 方法?这可能是通过预检请求所必需的。 我找到了解决办法,是responseHeader问题

以上是关于如何使用签名的 URL 将文件上传到谷歌云存储桶的主要内容,如果未能解决你的问题,请参考以下文章

使用 SSIS 将本地文件上传到谷歌云存储桶

将缓冲区上传到谷歌云存储

我无法使用 python 脚本将文件上传到谷歌云?

使用 multer 和 nodejs 将图像上传到谷歌云存储时出错

如何将数据附加到谷歌云存储上的文件

如何从应用引擎将写入附加到谷歌云存储文件?