本文属于机器翻译版本。若本译文内容与英语原文存在差异,则一律以英文原文为准。
在版本 3 中使用 Amazon S3 分段上 AWS SDK for PHP 传
单独的 PutObject
操作可上传的对象大小上限为 5 GB。但使用分段上传方法(例如,CreateMultipartUpload
、UploadPart
、CompleteMultipartUpload
、AbortMultipartUpload
),上传对象的大小范围可以在 5 MB 到 5 TB 之间。
以下示例演示如何:
-
使用将对象上传到 Amazon S3 ObjectUploader。
-
使用MultipartUploader为 Amazon S3 对象创建分段上传。
-
使用将对象从一个 Amazon S3 位置复制到另一个位置ObjectCopier。
的所有示例代码都可以在此 AWS SDK for PHP 处找到 GitHub
凭证
在运行示例代码之前,请配置您的 AWS 证书,如中所述凭证。然后导入 AWS SDK for PHP,如中所述基本用法。
对象上传程序
如果您不确定是否PutObject
或最MultipartUploader
适合该任务,请使用ObjectUploader
。 ObjectUploader
根据有效负载大小,使用PutObject
或MultipartUploader
将大文件上传到 Amazon S3。
require 'vendor/autoload.php'; use Aws\Exception\MultipartUploadException; use Aws\S3\MultipartUploader; use Aws\S3\ObjectUploader; use Aws\S3\S3Client;
示例代码
// Create an S3Client. $s3Client = new S3Client([ 'profile' => 'default', 'region' => 'us-east-2', 'version' => '2006-03-01' ]); $bucket = 'your-bucket'; $key = 'my-file.zip'; // Use a stream instead of a file path. $source = fopen('/path/to/large/file.zip', 'rb'); $uploader = new ObjectUploader( $s3Client, $bucket, $key, $source ); do { try { $result = $uploader->upload(); if ($result["@metadata"]["statusCode"] == '200') { print('<p>File successfully uploaded to ' . $result["ObjectURL"] . '.</p>'); } print($result); // If the SDK chooses a multipart upload, try again if there is an exception. // Unlike PutObject calls, multipart upload calls are not automatically retried. } catch (MultipartUploadException $e) { rewind($source); $uploader = new MultipartUploader($s3Client, $source, [ 'state' => $e->getState(), ]); } } while (!isset($result)); fclose($source);
配置
ObjectUploader
对象构造函数接受以下参数:
$client
-
用于执行转移的
Aws\ClientInterface
对象。它应是Aws\S3\S3Client
的实例。 $bucket
-
(
string
,必需)对象要上传到的存储桶名称。 $key
-
(
string
,必需)上传对象使用的键。 $body
-
(
mixed
,必需)要上传的对象数据。可以是StreamInterface
、PHP流资源或要上传的数据字符串。 $acl
-
(
string
ACL) 要在正在上传的对象上设置的访问控制列表 ()。默认情况下对象是私有的。 $options
-
用于分段上传的配置选项的关联数组。以下配置选项有效:
add_content_md5
-
(
bool
) 设置为 true 可自动计算上传的MD5校验和。 mup_threshold
-
(
int
,默认:int(16777216)
)文件大小的字节数。如果文件大小超过此限制,则使用分段上传。 before_complete
-
(
callable
) 在CompleteMultipartUpload
操作之前调用的回调。此回调应具有类似function (Aws\Command $command) {...}
的函数签名。有关可以添加到CommandInterface
对象的参数,请参阅CompleteMultipartUpload API参考资料。 before_initiate
-
(
callable
) 在CreateMultipartUpload
操作之前调用的回调。此回调应具有类似function (Aws\Command $command) {...}
的函数签名。如果文件大小超过该值,则调SDK用此回调。mup_threshold
有关可以添加到CommandInterface
对象的参数,请参阅CreateMultipartUpload API参考资料。 before_upload
-
(
callable
) 在任何PutObject
或UploadPart
操作之前调用的回调。此回调应具有类似function (Aws\Command $command) {...}
的函数签名。如果文件大小小于或等于该值,则调用此回SDK调。mup_threshold
有关您可以应用于PutObject
请求的参数,请参阅PutObject API参考资料。有关适用于UploadPart
请求的参数,请参阅UploadPart API参考资料。SDK忽略任何不适用于CommandInterface
对象所表示的操作的参数。 concurrency
-
(
int
,默认:int(3)
)在分段上传期间允许的并发UploadPart
操作数量上限。 part_size
-
(
int
,默认:int(5242880)
)进行分段上传时使用的分段大小(以字节为单位)。此值必须在 5 MB(含)和 5 GB(含)之间。 state
-
(
Aws\Multipart\UploadState
) 表示分段上传状态的对象,用于重新开始上次上传。如果提供了此选项,将忽略$bucket
和$key
参数以及part_size
选项。 params
-
为每个子命令提供配置选项的关联数组。例如:
new ObjectUploader($bucket, $key, $body, $acl, ['params' => ['CacheControl' =>
<some_value>
])
MultipartUploader
分段上传可改善较大对象的上传体验。这种方法支持您将对象分成各自独立的部分,既可以按任何顺序上传,也可并行上传。
我们鼓励 Amazon S3 客户针对大于 100 MB 的对象使用分段上传。
MultipartUploader 对象
SDK有一个特殊的MultipartUploader
对象,可以简化分段上传过程。
导入
require 'vendor/autoload.php'; use Aws\Exception\MultipartUploadException; use Aws\S3\MultipartUploader; use Aws\S3\S3Client;
示例代码
$s3Client = new S3Client([ 'profile' => 'default', 'region' => 'us-west-2', 'version' => '2006-03-01' ]); // Use multipart upload $source = '/path/to/large/file.zip'; $uploader = new MultipartUploader($s3Client, $source, [ 'bucket' => 'your-bucket', 'key' => 'my-file.zip', ]); try { $result = $uploader->upload(); echo "Upload complete: {$result['ObjectURL']}\n"; } catch (MultipartUploadException $e) { echo $e->getMessage() . "\n"; }
这个上传工具可根据提供的源和配置创建分段数据的生成器,并尝试上传所有分段。如果某些分段上传失败,上传工具将继续上传后面的分段,直到所有源数据均被读取。然后,上传工具重新尝试上传失败的分段,或引发包含有关无法上传的分段的信息的异常。
自定义分段上传
您可以设置 CreateMultipartUpload
、UploadPart
和 CompleteMultipartUpload
操作的自定义选项,分段上传工具可通过传递给构造函数的回调执行这些操作。
导入
require 'vendor/autoload.php'; use Aws\S3\MultipartUploader; use Aws\S3\S3Client;
示例代码
// Create an S3Client $s3Client = new S3Client([ 'profile' => 'default', 'region' => 'us-west-2', 'version' => '2006-03-01' ]); // Customizing a multipart upload $source = '/path/to/large/file.zip'; $uploader = new MultipartUploader($s3Client, $source, [ 'bucket' => 'your-bucket', 'key' => 'my-file.zip', 'before_initiate' => function (Command $command) { // $command is a CreateMultipartUpload operation $command['CacheControl'] = 'max-age=3600'; }, 'before_upload' => function (Command $command) { // $command is an UploadPart operation $command['RequestPayer'] = 'requester'; }, 'before_complete' => function (Command $command) { // $command is a CompleteMultipartUpload operation $command['RequestPayer'] = 'requester'; }, ]);
分段上传之间的手动垃圾回收
如果您在上传大量文件时达到了内存限制,则可能是由于在达到内存限制时,PHP垃圾收集器SDK
$uploader = new MultipartUploader($client, $source, [ 'bucket' => 'your-bucket', 'key' => 'your-key', 'before_upload' => function(\Aws\Command $command) { gc_collect_cycles(); } ]);
从错误中恢复
如果在分段上传过程中发生错误,将引发 MultipartUploadException
。可通过此异常访问 UploadState
对象,其中包含分段上传的进度信息。可使用 UploadState
重新开始未完成的上传。
导入
require 'vendor/autoload.php'; use Aws\Exception\MultipartUploadException; use Aws\S3\MultipartUploader; use Aws\S3\S3Client;
示例代码
// Create an S3Client $s3Client = new S3Client([ 'profile' => 'default', 'region' => 'us-west-2', 'version' => '2006-03-01' ]); $source = '/path/to/large/file.zip'; $uploader = new MultipartUploader($s3Client, $source, [ 'bucket' => 'your-bucket', 'key' => 'my-file.zip', ]); //Recover from errors do { try { $result = $uploader->upload(); } catch (MultipartUploadException $e) { $uploader = new MultipartUploader($s3Client, $source, [ 'state' => $e->getState(), ]); } } while (!isset($result)); //Abort a multipart upload if failed try { $result = $uploader->upload(); } catch (MultipartUploadException $e) { // State contains the "Bucket", "Key", and "UploadId" $params = $e->getState()->getId(); $result = $s3Client->abortMultipartUpload($params); }
若通过 UploadState
继续上传,将尝试上传尚未上传的分段。状态对象会跟踪缺少的分段,即使这些分段是不连续的。上传工具会读取或搜寻提供的源文件,找到仍需上传的特定分段的字节范围。
UploadState
对象是序列化的,因此您也可以在另一进程中重新开始上传。即使不是在处理异常,您也可以通过调用 $uploader->getState()
获得 UploadState
对象。
重要
作为源传递到 MultipartUploader
的流在上传之前不会自动倒回。如果您在与上个示例类似的循环中使用流,而不是文件路径,请重置 catch
块中的 $source
变量。
导入
require 'vendor/autoload.php'; use Aws\Exception\MultipartUploadException; use Aws\S3\MultipartUploader; use Aws\S3\S3Client;
示例代码
// Create an S3Client $s3Client = new S3Client([ 'profile' => 'default', 'region' => 'us-west-2', 'version' => '2006-03-01' ]); //Using stream instead of file path $source = fopen('/path/to/large/file.zip', 'rb'); $uploader = new MultipartUploader($s3Client, $source, [ 'bucket' => 'your-bucket', 'key' => 'my-file.zip', ]); do { try { $result = $uploader->upload(); } catch (MultipartUploadException $e) { rewind($source); $uploader = new MultipartUploader($s3Client, $source, [ 'state' => $e->getState(), ]); } } while (!isset($result)); fclose($source);
中止分段上传
通过检索 UploadState
对象中包含的 UploadId
并将其传递给 abortMultipartUpload
可以中止分段上传。
try { $result = $uploader->upload(); } catch (MultipartUploadException $e) { // State contains the "Bucket", "Key", and "UploadId" $params = $e->getState()->getId(); $result = $s3Client->abortMultipartUpload($params); }
异步分段上传
在 upload()
上调用 MultipartUploader
是一个阻止请求。如果在异步环境中工作,可获得分段上传的 Promise。
require 'vendor/autoload.php'; use Aws\S3\MultipartUploader; use Aws\S3\S3Client;
示例代码
// Create an S3Client $s3Client = new S3Client([ 'profile' => 'default', 'region' => 'us-west-2', 'version' => '2006-03-01' ]); $source = '/path/to/large/file.zip'; $uploader = new MultipartUploader($s3Client, $source, [ 'bucket' => 'your-bucket', 'key' => 'my-file.zip', ]); $promise = $uploader->promise();
配置
MultipartUploader
对象构造函数接受以下参数:
-
$client
-
用于执行转移的
Aws\ClientInterface
对象。它应是Aws\S3\S3Client
的实例。 -
$source
-
上传的源数据。这可以是路径或URL(例如
/path/to/file.jpg
)、资源句柄(例如,fopen('/path/to/file.jpg', 'r)
)或 PSR-7 流的实例。 -
$config
-
用于分段上传的配置选项的关联数组。
以下配置选项有效:
-
acl
-
(
string
ACL) 要在正在上传的对象上设置的访问控制列表 ()。默认情况下对象是私有的。 -
before_complete
-
(
callable
) 在CompleteMultipartUpload
操作之前调用的回调。此回调应具有类似function (Aws\Command $command) {...}
的函数签名。 -
before_initiate
-
(
callable
) 在CreateMultipartUpload
操作之前调用的回调。此回调应具有类似function (Aws\Command $command) {...}
的函数签名。 -
before_upload
-
(
callable
) 在任何UploadPart
操作之前调用的回调。此回调应具有类似function (Aws\Command $command) {...}
的函数签名。 -
bucket
-
(
string
,必需)对象要上传到的存储桶名称。 -
concurrency
-
(
int
,默认:int(5)
)在分段上传期间允许的并发UploadPart
操作数量上限。 -
key
-
(
string
,必需)上传对象使用的键。 -
part_size
-
(
int
,默认:int(5242880)
)进行分段上传时使用的分段大小(以字节为单位)。它必须在 5 MB(含)和 5 GB(含)之间。 -
state
-
(
Aws\Multipart\UploadState
) 表示分段上传状态的对象,用于重新开始上次上传。如果提供了此选项,将忽略bucket
、key
和part_size
选项。 add_content_md5
-
(
boolean
) 设置为 true 可自动计算上传的MD5校验和。 params
-
为每个子命令提供配置选项的关联数组。例如:
new MultipartUploader($client, $source, ['params' => ['CacheControl' =>
<some_value>
]])
-
分段副本
AWS SDK for PHP 还包括一个MultipartCopy
对象,该对象的使用方式与类似MultipartUploader
,但设计用于在 Amazon S3 中复制大小在 5 GB 到 5 TB 之间的对象。
require 'vendor/autoload.php'; use Aws\Exception\MultipartUploadException; use Aws\S3\MultipartCopy; use Aws\S3\S3Client;
示例代码
// Create an S3Client $s3Client = new S3Client([ 'profile' => 'default', 'region' => 'us-west-2', 'version' => '2006-03-01' ]); //Copy objects within S3 $copier = new MultipartCopy($s3Client, '/bucket/key?versionId=foo', [ 'bucket' => 'your-bucket', 'key' => 'my-file.zip', ]); try { $result = $copier->copy(); echo "Copy complete: {$result['ObjectURL']}\n"; } catch (MultipartUploadException $e) { echo $e->getMessage() . "\n"; }