2016-02-02 25 views
6

Tôi đang làm việc trên một dự án liên quan đến việc tạo các URL S3 mà người khác có thể sử dụng để tải tệp lên thùng S3 của tôi. Dưới đây là một ví dụ làm việc tối thiểu:AWS PHP SDK: Giới hạn kích thước tải lên tệp S3 trong URL được chỉ định

<?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(); 

?> 

Bây giờ, nếu tôi đặt tập tin đó tại một địa điểm truy cập bằng Internet, máy chủ web của tôi có thể được sử dụng để lấy URL upload ký mới:

$ 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... 
$ 

này thành công tải lên một tệp cục bộ vào nhóm của tôi, vì vậy tôi có thể chơi với nó trong S3.

Giả sử rằng tôi không quá lo lắng về việc mọi người tạo nhiều URL và tải lên nhiều tệp vào thùng của tôi trong một khoảng thời gian ngắn, nhưng tôi muốn giới hạn kích thước tệp tải lên. Nhiều tài nguyên đề xuất đính kèm chính sách cho URL đã ký:

<?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(); 

?> 

Phiên bản này tạo URL (không có dấu hiệu lỗi) có thể được sử dụng theo cùng một cách. Tôi không chắc liệu tôi có cần một số điều kiện trong chính sách này hay không (acl, bucket, starts-with), nhưng tôi không nghĩ rằng việc bao gồm các điều kiện đó sẽ vi phạm chính sách.

Về lý thuyết, cố gắng sử dụng URL đã ký này để tải lên tệp lớn hơn 8 KiB sẽ khiến S3 hủy bỏ quá trình tải lên. Tuy nhiên, thử nghiệm này với một tập tin lớn hơn cho thấy rằng curl vẫn hạnh phúc tải lên các tập tin:

$ 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... 
$ 

Kiểm tra xô cho thấy, trên thực tế, các tập tin lớn đã được tải lên, và kích thước của tập tin là lớn hơn so với chính sách được cho là chỉ ra.

Kể từ khi các trang khác nhau hiển thị cách khác nhau để gắn chính sách này, tôi cũng đã thử các phiên bản sau:

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

Tuy nhiên, các URL được tạo ra với bất kỳ của các phiên bản này cho phép các file lớn hơn kích thước quy định để được tải lên.

Tôi có đính kèm chính sách không chính xác hoặc có giới hạn cơ bản để hạn chế tải lên S3 theo cách này không?

Đối với máy chủ web của tôi, tôi đang sử dụng HHVM 3.11.1 với phiên bản 3.14.1 của SDK AWS cho PHP.

Trả lời

3

Chính sách tải lên S3 không thể được sử dụng với URL được ký trước.

Tài liệu chính sách có thể được sử dụng với browser uploads to S3 using HTML POST Forms.

URL được ký trướcBiểu mẫu POST HTML là hai phương pháp tải lên S3 khác nhau. Các cựu được cho là đơn giản, nhưng ít linh hoạt, hơn sau này.

CẬP NHẬT

Nếu bạn phải tải lên các tập tin mà không cần dùng một trình duyệt, yêu cầu POST Form của HTML có thể được sao chép sử dụng curl chức năng của PHP, thư viện như Guzzle, hoặc bằng cách sử dụng dòng lệnh như sau :

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

Tôi biết rằng các hình thức HTML POST là một lựa chọn, nhưng tôi không độc quyền nhắm mục tiêu các trình duyệt, do đó không phải là một giải pháp trong trường hợp của tôi. Cám ơn vì sự gợi ý! – millinon

+0

Các trường POST phức tạp hơn một chút so với những gì tôi đang thực hiện - Tôi thực sự muốn tạo một URL duy nhất có thể được sao chép/dán vào bất kỳ ứng dụng khách nào hỗ trợ HTTP PUT. Mặc dù tôi rất thích giải pháp này - các máy khách hỗ trợ HTTP PUT có lẽ cũng sẽ hỗ trợ các trường POST, vì vậy tôi sẽ cố gắng cung cấp phương thức này để tải lên. – millinon

2

bạn có thể cố gắng thêm các chính sách cụ thể để xô bạn

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

và sau này, chỉ cần sử dụng bình thường putObject lệnh

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

Tôi nghĩ đây là hướng đi đúng - tôi cần đính kèm chính sách vào chính thùng, chứ không phải chính yêu cầu của PutObject. Tuy nhiên, có vẻ như 'độ dài nội dung 'chỉ được hỗ trợ là điều kiện chính sách tải lên trình duyệt, vì vậy tôi không chắc chắn rằng có thể bao gồm giới hạn kích thước tệp trong URL được chỉ định hoặc dưới dạng thuộc tính của chính nhóm đó. – millinon

+0

Có ai có thể xác nhận điều này có hiệu quả hay không? – CamHart

Các vấn đề liên quan