本文為英文版的機器翻譯版本,如內容有任何歧義或不一致之處,概以英文版為準。
將 Amazon S3 分段上傳與AWS SDK for PHP版本 3 搭配使用
透過單次 PutObject
操作,您最多可上傳大小 5 GB 的物件。不過,如果使用分段上傳方法 (例如,CreateMultipartUpload
、UploadPart
、CompleteMultipartUpload
、AbortMultipartUpload
),您可以上傳大小從 5 MB 到 5 TB 的物件。
下列範例將說明:
-
使用將物件上傳到 Amazon S3 ObjectUploader。
-
使MultipartUploader用建立 Amazon S3 物件的多部分上傳。
-
使用將物件從一個 Amazon S3 位置複製到另一個位置ObjectCopier。
所有的範例程式碼都可以AWS SDK for PHP在這裡取
登入資料
在執行範例程式碼之前,請依照中的說明設定您的AWS認證憑證。然後匯入AWS SDK for PHP,如中所述基本使用。
對象上傳
如果您不確定MultipartUploader
是PutObject
否最適合該任務,請使用ObjectUploader
。 ObjectUploader
使用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
)在任何PutObject
或UploadPart
操作之前調用的回調。回調應具有類似於:的函數簽名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"; }
上傳程式會根據隨附的原始碼和組態,建立分段資料的產生器,並嘗試上傳所有部分。如果某些部分上傳失敗,上傳程式會持續上傳之後的部分,直到讀取完整個原始碼的資料。之後,上傳工具會嘗試上傳失敗的部分,或擲出包含與無法上傳之部分相關資訊的例外狀況。
自訂多部分上傳
您可以透過將回呼函式傳遞至其建構函式,來針對多段上傳程式所執行的 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 廢棄項目收集器
$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
) 代表分段上傳狀態的物件,用來恢復先前的上傳作業。提供此選項時,會略過bucket
、key
和part_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"; }