將 Amazon S3 分段上傳與 AWS SDK for PHP 版本 3 搭配使用 - AWS SDK for PHP

本文為英文版的機器翻譯版本,如內容有任何歧義或不一致之處,概以英文版為準。

將 Amazon S3 分段上傳與 AWS SDK for PHP 版本 3 搭配使用

透過單次 PutObject 操作,您最多可上傳大小 5 GB 的物件。不過,如果使用分段上傳方法 (例如,CreateMultipartUploadUploadPartCompleteMultipartUploadAbortMultipartUpload),您可以上傳大小從 5 MB 到 5 TB 的物件。

下列範例將說明:

所有 的範例程式碼 AWS SDK for PHP 都可在 GitHub 上取得

登入資料

在執行範例程式碼之前,請先設定您的 AWS 憑證,如 中所述憑證。然後匯入 AWS SDK for PHP,如 中所述基本使用

物件上傳程式

如果您不確定 PutObjectMultipartUploader 是否最適合任務,請使用 ObjectUploader。 會根據承載大小MultipartUploader,使用 PutObject或 將大型檔案ObjectUploader上傳至 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 Word參考

before_initiate

(callable) 要在 CreateMultipartUpload 操作之前呼叫的回呼函式。回呼應具有類似 的函數簽章:function (Aws\Command $command) {...}。如果檔案大小超過 mup_threshold值,SDK 會叫用此回呼。如需可新增至CommandInterface物件的參數,請參閱 CreateMultipartUpload API Word參考

before_upload

(callable) 回撥以在任何 PutObjectUploadPart操作之前叫用 。回呼應具有類似 的函數簽章:function (Aws\Command $command) {...}。如果檔案大小小於或等於mup_threshold值,SDK 會叫用此回呼。如需可套用至PutObject請求的參數,請參閱 PutObject API Word參考。如需套用至UploadPart請求的參數,請參閱 UploadPart API Word參考。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"; }

上傳程式會根據隨附的原始碼和組態,建立分段資料的產生器,並嘗試上傳所有部分。如果某些部分上傳失敗,上傳程式會持續上傳之後的部分,直到讀取完整個原始碼的資料。之後,上傳工具會嘗試上傳失敗的部分,或擲出包含與無法上傳之部分相關資訊的例外狀況。

自訂分段上傳

您可以透過將回呼函式傳遞至其建構函式,來針對多段上傳程式所執行的 CreateMultipartUploadUploadPartCompleteMultipartUpload 操作,設定自訂選項。

匯入

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'; }, ]);

部分上傳之間的手動垃圾收集

如果您使用大型上傳達到記憶體限制,這可能是因為 SDK 垃圾收集器在達到記憶體限制時尚未收集到 PHP 產生的循環參考。在操作之間手動叫用集合演算法會允許在達到該限制前收集循環。以下範例會在每次分段上傳前,使用回呼叫用集合演算法。請注意,叫用廢棄項目收集器不會伴隨效能成本,最佳使用方式將取決於您的使用案例和環境。

$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) 代表分段上傳狀態的物件,用來恢復先前的上傳作業。提供此選項時,會略過 bucketkeypart_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"; }