【问题标题】:Google Storage signedUploadUrl, fetching upload url returns: Bad content type. Please use multipartGoogle Storage signedUploadUrl,获取上传网址返回:错误的内容类型。请使用多部分
【发布时间】:2020-06-10 05:56:57
【问题描述】:

我想让我的用户将大文件直接上传到 Google 存储。根据this documentation,我应该能够使用 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。

...

为了上传数据,必须通过发送一个会话 URI 对此方法返回的 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.

【问题讨论】:

  • 您似乎正在尝试开始可恢复上传。开始可恢复上传的请求是 POST 请求。您的 PHP 代码正在签署执行 PUT 请求的请求。
  • 您必须使用登录实际请求时指定的相同 HTTP 方法。在您的情况下,您应该使用 PUT 方法。对于curl,使用-T 选项。您提到“大文件”。任何大于几百兆字节的数据都可能导致糟糕的用户体验。
  • @JohnHanley PUT 是最终的上传请求应该是什么,但我仍处于尝试获取我可以 PUT 的 uri 的中间步骤,并且该请求需要根据文档发布 POST 。此上传将在 iOS 应用的后台进行,用户体验会很好。
  • @BrandonYarbrough PUT 是最终的上传请求应该是什么,但我仍处于尝试获取我可以 PUT 的 uri 的中间步骤,并且该请求需要根据文档发布 POST。
  • 我评论的重点是签名中指定的方法必须与请求方法匹配。接下来,你要文件上传还是resumable文件上传?在第一种情况下使用 PUT,在第二种情况下使用 POST。 curl 支持第一种方法。上传Tpe参考此链接:cloud.google.com/storage/docs/json_api/v1/objects/insert

标签: php google-cloud-platform google-cloud-storage php-7 google-cloud-php-client


【解决方案1】:

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

【讨论】:

  • 我得到了同样的回应。 Bad content type. Please use multipart.
  • 我正在上传一个大文件并将其与表单值一起发布。似乎没有任何工作。 (使用 PHP 5 createUploadUrl 完美运行)
【解决方案2】:

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

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

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

【讨论】:

  • 我正在尝试生成上传网址,该网址将传递给 iOS 应用,以便 iOS 应用可以在后台上传文件。
【解决方案3】:

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

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

我最初的 curl 测试失败的原因是因为上传 url 包含标准查询参数,其中包括 &,当我通过 system() 运行 curl 命令时,这些参数搞砸了命令。

因此,使用简单的signedUrl() 方法返回原始 curl PUT 请求,错误命令如下所示:

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"

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2015-09-04
    • 1970-01-01
    • 2012-08-10
    • 1970-01-01
    • 1970-01-01
    • 2019-12-24
    • 2016-12-22
    • 2019-09-08
    相关资源
    最近更新 更多