1

我想让我的用户直接将大文件上传到 Google 存储。根据此文档,我应该能够使用 PHP SDK 生成签名的上传 url。我这样做是这样的:

$storage = new StorageClient(['keyFilePath' =>  $myKeyPath ]);

$bucket = $storage->bucket($bucketname);
$object = $bucket->object($relativepath);

$sessionURI = $object->signedUploadUrl(
    # This URL is valid for 15 minutes
    new \DateTime('15 min'),
    [
        'method' => 'PUT',
        'contentType' => 'application/octet-stream',
        'version' => 'v4',
    ]
);

文档说我需要POST返回$sessionURI才能获得我可以上传到的实际网址。文档:

签名上传网址

为此对象创建一个签名上传 URL。

...

为了上传数据,必须通过向此方法返回的 URL 发送 HTTP POST 请求来获取会话 URI。

但是,当我尝试到POST$sessionURI,我收到错误:

POST object expects Content-Type multipart/form-data

所以,我明确地设置了Content-Typemultipart/form-data然后我得到了错误:

Bad content type. Please use multipart.

我已经尝试从代码中执行此操作以及在命令行上使用 curl ,并且我尝试设置Content-Type但似乎没有任何效果(我添加了一些新行以使其可读,但最初都是一行):

/usr/bin/curl -X POST -H "Content-Type: multipart/form-data" 
https://storage.googleapis.com/my-project-id.appspot.com/uploads/uploadfilename.jpg?GoogleAccessId=myserviceaccount
@mydomain.com&Expires=1591657512&Signature=veryverylongsignatureasdfasdfasdfasdfadfa
sdfasdfasdfasdfasdfasdfasdfasdfasdfadsfasdfasdfasdfasdfasdfasdfasdfasdfasdfasdfasdfa
sdfasdfasdfasdfasdfasdfasdfasdfasdf

我尝试了一堆不同的示例,并且尝试完全按照文档中的说明进行操作,但似乎没有任何效果。

我错过了什么?我究竟做错了什么?

- - 更新

我尝试使用 Google 的示例代码回到开头,但仍然无法正常工作。这是 Google 的示例代码给我的 curl 命令:

curl -X PUT -H 'Content-Type: application/octet-stream' --upload-file /path/to/file.jpg 
https://storage.googleapis.com/my-project-id.appspot.com/uploads/uploadfilename.jpg?GoogleAccessId=myserviceaccount
@mydomain.com&Expires=1591657512&Signature=veryverylongsignatureasdfasdfasdfasdfadfa
sdfasdfasdfasdfasdfasdfasdfasdfasdfadsfasdfasdfasdfasdfasdfasdfasdfasdfasdfasdfasdfa
sdfasdfasdfasdfasdfasdfasdfasdfasdf

那给了我:

Anonymous caller does not have storage.objects.create access to the Google Cloud Storage object.

4

3 回答 3

0

您发布到的端点似乎不接受表单多部分数据。尝试将您的 Content-Type 设置为“multipart/related”而不是“multipart/form-data”,看看您是否能够继续。检查此链接云存储上传以获得更多帮助。

于 2020-06-08T23:23:10.580 回答
0

我最初尝试了 google 提供的示例代码,但没有成功(这是两步 signedUrl() 方法,只需要一个 api 调用和一个 PUT 调用),所以我经历了多次迭代尝试不同的函数和不同的方法,遵循网络上的不同示例,所有这些都失败了(包括需要 api 调用、POST 和另一个 POST(或者可能是 PUT)的三步 signedUploadUrl() 方法)。

我仍然需要弄清楚如何让它在我的应用程序中工作,但我至少让它与 curl 一起工作,这是权限和 api 调用的概念证明。

我最初的 curl 测试失败的原因是因为上传 url 包含标准查询参数,&当我通过system().

所以,用简单的方法回到原来的 curl PUT 请求signedUrl(),错误的命令看起来像这样:

curl -X PUT -H 'Content-Type: application/octet-stream' --upload-file /path/to/file.jpg 
https://storage.googleapis.com/my-project-id.appspot.com/uploads/uploadfilename.jpg?GoogleAccessId=myserviceaccount
@mydomain.com&Expires=1591657512&Signature=veryverylongsignatureasdfasdfasdfasdfadfa
sdfasdfasdfasdfasdfasdfasdfasdfasdfadsfasdfasdfasdfasdfasdfasdfasdfasdfasdfasdfasdfa
sdfasdfasdfasdfasdfasdfasdfasdfasdf

而工作命令在 URL 周围包含引号以避免 shell 抓取和解释&s:

curl -X PUT -H 'Content-Type: application/octet-stream' --upload-file /path/to/file.jpg 
"https://storage.googleapis.com/my-project-id.appspot.com/uploads/uploadfilename.jpg?GoogleAccessId=myserviceaccount
@mydomain.com&Expires=1591657512&Signature=veryverylongsignatureasdfasdfasdfasdfadfa
sdfasdfasdfasdfasdfasdfasdfasdfasdfadsfasdfasdfasdfasdfasdfasdfasdfasdfasdfasdfasdfa
sdfasdfasdfasdfasdfasdfasdfasdfasdf"
于 2020-06-09T21:55:52.633 回答
0

如果您邀请用户通过 HTML 表单上传文件,您需要使用Bucket::generatedSignedPostPolicyV4.

该方法将返回一个数组,其中包含一个操作 URI(用于您的<form action>属性)和一个您需要包含在表单中的字段列表。遍历这些并使用隐藏输入将它们嵌入为键/值字段。

上面链接中示例的格式似乎有些混乱,但您可以在源代码中看到完整的(如果简化的话)示例。

于 2020-06-09T13:52:15.380 回答