將 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,如中所述基本使用

對象上傳

如果您不確定MultipartUploaderPutObject否最適合該任務,請使用ObjectUploaderObjectUploader使用PutObject或將大型檔案上傳到 Amazon S3MultipartUploader,這取決於最佳根據承載大小的內容而定。

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) {...}

before_initiate

(callable) 要在 CreateMultipartUpload 操作之前呼叫的回呼函式。回調應具有類似於:的函數簽名function (Aws\Command $command) {...}

before_upload

callable)在任何PutObjectUploadPart操作之前調用的回調。回調應具有類似於:的函數簽名function (Aws\Command $command) {...}

concurrency

(int預設int(3)) 分段上傳期間所允許的並行 UploadPart 操作的數目上限。

part_size

(int預設int(5242880)) 進行分段上傳時所使用的分段大小 (位元組)。此值必須介於 5 MB 到 5 GB (含) 之間。

state

(Aws\Multipart\UploadState) 代表分段上傳狀態的物件,用來恢復先前的上傳作業。提供此選項時,會忽略$bucket$key引數和part_size選項。

MultipartUploader

分段上傳是專為改善較大型物件上傳的體驗所設計。這些方法可讓您以任意順序,個別同時上傳物件的各部分。

建議 Amazon S3 客戶對大於 100 MB 的物件使用分段上傳。

MultipartUploader 物件

軟體開發套件具有特殊的 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'; }, ]);

零件上傳之間的手動資源回收

如果您達到大型上傳的記憶體限制,這可能是因為在達到記憶體限制時,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 stream 的執行個體。

$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 總和檢查碼。

多部分副本

此外,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"; }