2016-02-02 24 views
6

他の人がS3バケットにファイルをアップロードするために使用できるS3 URLを生成するプロジェクトに取り組んでいます。ここでは、最小限の作業例です:私は、インターネットからアクセス可能な場所にそのファイルを置けば、今AWS PHP SDK:限定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(); 

?> 

、私のウェブサーバは、新しい署名アップロードURLを取得するために使用することができます成功し

$ 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を生成します。私は、ポリシー(aclbucketstarts-with)にこれらの条件の一部が必要かどうかはわかりませんが、それらを含めてポリシーを破るとは思いません。

理論上、署名されたURLを使用して8 KiBを超えるファイルをアップロードしようとすると、S3はアップロードを中止するはずです。

バケットをチェック
$ 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... 
$ 

は確かに、大きなファイルがアップロードされた、ことを示しており、ファイルのサイズは、政策はおそらく示しよりも大きい。しかし、大きなファイルでこれをテストすることcurlはまだ喜んでファイルをアップロードすることを示しています。

さまざまなページがポリシーを取り付けるのさまざまな方法を示しているので、私はまた、次のバージョン試してみました:

'Policy' => json_encode($policy) 
'Policy' => base64_encode(json_encode($policy)) 

をただし、これらのバージョンのいずれかで生成されたURLは、アップロードする指定したサイズを超えるファイルを許可します。

ポリシーを誤って添付していますか、このようにS3へのアップロードを制限することに基本的な制限がありますか?

私のWebサーバーでは、PHP用AWS SDKのバージョン3.14.1でHHVM 3.11.1を使用しています。

答えて

3

S3アップロードポリシーは、署名済みのURLでは使用できません。

browser uploads to S3 using HTML POST Formsでポリシー文書を使用できます。

事前に署名されたURLHTML POSTフォームは、S3にアップロードする2つの異なる方法です。前者は間違いなく簡単ですが、後者より柔軟性がありません。あなたは、ブラウザを使用せずにファイルをアップロードする必要がある場合は

UPDATEは

、HTML POSTフォームの要求はGuzzleようなPHPのcurl機能、ライブラリを使用して、または次のようにコマンドラインを使用して再現することができます:

curl 'https://s3-bucket.s3.amazonaws.com/' \ 
    -F 'key=uploads/${filename}' \ 
    -F 'AWSAccessKeyId=YOUR_AWS_ACCESS_KEY' \ 
    -F 'acl=private' \ 
    -F 'success_action_redirect=http://localhost/' \ 
    -F 'policy=YOUR_POLICY_DOCUMENT_BASE64_ENCODED' \ 
    -F 'signature=YOUR_CALCULATED_SIGNATURE' \ 
    -F 'Content-Type=image/jpeg' \ 
    -F '[email protected]' 
+0

私は、HTML POSTフォームがオプションであることを知っているが、私は排他的にブラウザをターゲットにいないよ、だから、私の場合は解決策ではありません。提案していただきありがとうございます! – millinon

+0

POSTフィールドは、私が進めているよりも少し複雑です - 私は実際にHTTP PUTをサポートしているクライアントにコピー/ペーストできる単一のURLを生成したいと思っています。私はこの解決策が大好きです。HTTP PUTをサポートしているクライアントもおそらくPOSTフィールドをサポートする予定ですので、アップロードの方法としてこれを提供するよう努力します。 – millinon

2

は、あなたのバケットに特定のポリシーを追加しようとすることができます

$s3client->putBucketPolicy(array(
    'Bucket' => $bucket, 
    'Policy' => json_encode(array(
     'conditions' => array(
      array(
       'content-length-range', 0, 8*1024, 
       'starts-with', '$key', 'tmp/' 
       ... 

この後、普通のputObjectコマンドを使用し

$command = $s3client->getCommand('PutObject', [ 
    'ACL' => 'private', 
    'Body' => '', 
    'Bucket' => 'mybucket', 
    'Key' => 'tmp/' . $id]); 
+0

私はこれが正しい方向だと思う - 私はバケット自体には、PutObject要求自体ではなく、ポリシーを添付する必要があります。しかし、 'content-length-range'はブラウザのアップロードポリシーの条件としてのみサポートされているようですので、ファイルサイズ制限をpresigned URLやバケット自体の属性として含めることはできません。 – millinon

+0

これはうまくいけば誰でも確認できますか? – CamHart

関連する問題