AWS SDK for PHP バージョン 3 での Amazon S3 マルチパートアップロードの使用 - AWS SDK for PHP

AWS SDK for PHP バージョン 3 での Amazon S3 マルチパートアップロードの使用

1 回の PutObject 操作では、合計サイズが 5 GB 以内のオブジェクトをアップロードできます。ただし、マルチパートアップロード手法 (たとえば、CreateMultipartUploadUploadPartCompleteMultipartUploadAbortMultipartUpload) を使用すると、合計サイズが 5 MB~5 TB のオブジェクトをアップロードできます。

以下の例では、次の方法を示しています。

  • ObjectUploader を使用して、オブジェクトを Amazon S3 にアップロードします。

  • MultipartUploader を使用して Amazon S3 オブジェクトのマルチパートアップロードを作成します。

  • ObjectCopier を使用して、1 つの Amazon S3 の場所から別の場所にオブジェクトをコピーします。

AWS SDK for PHP バージョン 3 用のすべてのサンプルコードは GitHub で入手できます。

認証情報

サンプルコードを実行する前に、「AWS SDK for PHP バージョン 3 の認証情報」の説明に従って AWS 認証情報を設定します。次に、「AWS SDK for PHP バージョン 3 の基本的な使用パターン」の説明に従って AWS SDK for PHP をインポートします。

オブジェクトアップローダー

PutObject または MultipartUploader がタスクに最適かどうかが不明な場合は、ObjectUploader を使用します。ObjectUploader は、ペイロードサイズに基づいてどれが最適かにより、PutObject または MultipartUploader を使用して大きなファイルを Amazon S3 にアップロードします。

require 'vendor/autoload.php'; use Aws\S3\S3Client; use Aws\Exception\AwsException; use Aws\S3\ObjectUploader;

サンプルコード

$s3Client = new S3Client([ 'profile' => 'default', 'region' => 'us-east-2', 'version' => '2006-03-01' ]); $bucket = 'your-bucket'; $key = 'my-file.zip'; // Using stream instead of 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); } catch (MultipartUploadException $e) { rewind($source); $uploader = new MultipartUploader($s3Client, $source, [ 'state' => $e->getState(), ]); } } while (!isset($result));

MultipartUploader

マルチパートアップロードは、大容量オブジェクトのアップロードを効率よく行えるように設計されています。マルチパートアップロードでは、オブジェクトを分割して、別々に任意の順序で並行してアップロードできます。

Amazon S3 のユーザーには、100 MB を超えるオブジェクトに対してマルチパートアップロードを使用することをお勧めします。

MultipartUploader オブジェクト

SDK には、マルチパートアップロードのプロセスを簡素化する特別な MultipartUploader オブジェクトがあります。

インポート

require 'vendor/autoload.php'; use Aws\S3\S3Client; use Aws\Exception\AwsException; use Aws\S3\MultipartUploader; use Aws\Exception\MultipartUploadException;

サンプルコード

$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\S3Client; use Aws\Exception\AwsException; use Aws\S3\MultipartUploader; use Aws\Exception\MultipartUploadException;

サンプルコード

// 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 (\Aws\Command $command) { // $command is a CreateMultipartUpload operation $command['CacheControl'] = 'max-age=3600'; }, 'before_upload' => function (\Aws\Command $command) { // $command is an UploadPart operation $command['RequestPayer'] = 'requester'; }, 'before_complete' => function (\Aws\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\S3\S3Client; use Aws\Exception\AwsException; use Aws\S3\MultipartUploader; use Aws\Exception\MultipartUploadException;

サンプルコード

// 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 オブジェクトはシリアル化可能であるため、別のプロセスでアップロードを再開することもできます。また、例外を処理していない場合でも、UploadState を呼び出すことによって $uploader->getState() オブジェクトを取得できます。

重要

MultipartUploader にソースとして渡されるストリームは、アップロード前に自動的には巻き戻しされません。そのため、前述の例のようなループでファイルパスではなくストリームを使用している場合は、catch ブロック内で $source 変数をリセットします。

インポート

require 'vendor/autoload.php'; use Aws\S3\S3Client; use Aws\Exception\AwsException; use Aws\S3\MultipartUploader; use Aws\Exception\MultipartUploadException;

サンプルコード

// 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));

マルチパートアップロードの中止

マルチパートアップロードは、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\S3Client; use Aws\Exception\AwsException; use Aws\S3\MultipartUploader; use Aws\Exception\MultipartUploadException;

サンプルコード

// 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 オプションは無視されます。

マルチパートコピー

AWS SDK for PHP には、5 GB 以上かつ 5 TB 以内のサイズのオブジェクトを Amazon S3 内でコピーするように設計されている MultipartCopy オブジェクトも含まれていて、MultipartUploader と同様の方法で使用できます。

require 'vendor/autoload.php'; use Aws\S3\S3Client; use Aws\Exception\AwsException; use Aws\S3\MultipartCopy; use Aws\Exception\MultipartUploadException;

サンプルコード

// 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"; }