我正在开发一个涉及生成S3 URL的项目,其他人可以使用它来将文件上传到我的S3存储桶 . 这是一个最小的工作示例:
<?php
require('aws.phar');
use Aws\S3\S3Client;
$s3client = new S3Client(...); // credentials go here
$id = uniqid(); // generate some kind of key
$command = $s3client->getCommand('PutObject', [
'ACL' => 'private',
'Body' => '',
'Bucket' => 'mybucket',
'Key' => 'tmp/' . $id]);
echo (string) $s3client->createPresignedRequest($command, '+5 minutes')->getURI();
?>
现在,如果我将该文件放在互联网可访问的位置,我的网络服务器可用于获取新签名的上传网址:
$ curl http://my.domain.com/some/page.php
https://s3.amazonaws.com/mybucket/tmp/someID?x-amz-acl=private&lots-of-aws-params...
$ curl -X PUT -d "@someFile" https://s3.amazonaws.com/mybucket/tmp/someID?x-amz-acl=private&lots-of-aws-params...
$
这会成功将本地文件上传到我的存储桶,因此我可以在S3中使用它 .
让我们假设我不太担心人们会在很短的时间内生成许多URL并将许多文件上传到我的存储桶,但我想限制上传文件的大小 . 许多资源建议将策略附加到签名URL:
<?php
require('aws.phar');
use Aws\S3\S3Client;
$s3client = new S3Client(...); // credentials go here
$id = uniqid(); // generate some kind of key
$policy = [
'conditions' => [
['acl' => 'private'],
['bucket' => 'mybucket'],
['content-length-range', 0, 8*1024], // 8 KiB
['starts-with', '$key', 'tmp/']
], 'expiration' =>
(new DateTime())->modify('+5 minutes')->format(DateTime::ATOM)];
$command = $s3client->getCommand('PutObject', [
'ACL' => 'private',
'Body' => '',
'Bucket' => 'mybucket',
'Key' => 'tmp/' . $id,
'Policy' => $policy]);
echo (string) $s3client->createPresignedRequest($command, '+5 minutes')->getURI();
?>
此版本生成可以以相同方式使用的URL(无任何错误指示) . 我不确定我是否需要政策中的某些条件( acl
, bucket
, starts-with
),但我不认为包含它们会违反政策 .
理论上,尝试使用此签名URL上传大于8 KiB的文件应导致S3中止上载 . 但是,使用更大的文件进行测试表明 curl
仍然可以愉快地上传文件:
$ ls -lh file.txt
-rw-rw-r-- 1 millinon millinon 210K Jan 2 00:41 file.txt
$ curl http://my.domain.com/some/page.php
https://s3.amazonaws.com/mybucket/tmp/someOtherID?x-amz-acl=private&lots-of-aws-params...
$ curl -X PUT -d "@file.txt" https://s3.amazonaws.com/mybucket/tmp/someOtherID?x-amz-acl=private&lots-of-aws-params...
$
检查存储桶显示确实上传了大文件,并且文件的大小大于所谓的策略 .
由于各种页面显示了附加策略的不同方式,我还尝试了以下版本:
'Policy' => json_encode($policy)
'Policy' => base64_encode(json_encode($policy))
但是,使用任何这些版本生成的URL都允许上载大于指定大小的文件 .
我是否错误地附加了该策略,或者是否存在以这种方式限制上传到S3的基本限制?
对于我的Web服务器,我使用的是适用于PHP的AWS SDK的3.14.1版HHVM 3.11.1 .
2 回答
S3上载策略不能与预签名URL一起使用 .
策略文档可与browser uploads to S3 using HTML POST Forms一起使用 .
预签名URL和HTML POST表单是上传到S3的两种不同方法 . 前者可以说比后者更简单,但更不灵活 .
UPDATE
如果您必须在不使用浏览器的情况下上传文件,请使用HTML POST表单's request can be reproduced using PHP' s
curl
函数,Guzzle等库,或使用命令行,如下所示:您可以尝试将特定策略添加到您的存储桶中吗?
在此之后,只需使用普通的putObject命令