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