我想让我的用户直接将大文件上传到Google存储空间。根据this documentation,我应该能够使用PHP SDK生成签名的上传网址。我是这样的:
$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
,然后才能获取可以上传到的ACTUAL网址。文档:
signedUploadUrl
为此对象创建一个签名的上载URL。
...
为了上传数据,必须通过发送 从此方法返回的URL的HTTP POST请求。
但是,当我尝试将POST
设置为$sessionURI
时,出现错误:
POST object expects Content-Type multipart/form-data
因此,我将Content-Type
显式设置为multipart/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.
似乎您要发布的端点不接受表单多部分数据。尝试将Content-Type设置为“ multipart / related”,而不是“ multipart / form-data”,然后查看是否可以继续。检查此链接Cloud Storage Upload以获取更多帮助。
如果邀请用户通过HTML表单上传文件,则需要使用Bucket::generatedSignedPostPolicyV4
。
该方法将返回一个数组,该数组包含一个动作URI(用于Bucket::generatedSignedPostPolicyV4
属性)以及需要包含在表单中的字段列表。对这些对象进行迭代,并使用隐藏的输入将它们作为键/值字段嵌入。
上面链接上的样本格式似乎有些混乱,但是您可以在<form action>
中看到完整的样本(如果已简化)。
我最初尝试了google提供的示例代码,但没有用(这是两步的signatureUrl()方法,只需要一个api调用和一个PUT调用),所以我经历了多次迭代,尝试了不同的功能和不同的方法(遵循网络上的不同示例),所有这些示例都一直失败(包括三步的signedUploadUrl()方法,该方法需要api调用,POST,然后是另一个POST(或可能是PUT))。
我仍然需要弄清楚如何使它在我的应用程序中正常工作,但是至少我可以使它与curl一起使用,这是对权限和api调用的概念证明。
我最初的curl测试失败的原因是,上传的URL包含标准查询参数,其中包括source code,而当我通过&
运行curl命令时,这些参数搞乱了该命令。
因此,使用简单的system()
方法返回原始的curl PUT请求,错误的命令如下所示:
signedUrl()
虽然工作命令在URL周围加上了引号,以避免shell抓取和解释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
:
&