Skip to content
これは pieceofcake2/async-aws のドキュメントです。pieceofcake2/cakephp 用の CakePHP 2.x プラグインです。 このフォークについて

S3 ​

S3 ストリームラッパー ​

S3 ストリームラッパーを使うと、PHP のファイル関数 (file_get_contents()、file_put_contents()、fopen()、 is_file()、scandir()、...) で s3://bucket/key パスを使えます。これは pieceofcake2/aws が登録する AWS SDK for PHP のストリームラッパー (Aws\S3\StreamWrapper) を AsyncAws に移植したもので、 対応範囲と制限も同じです。async-aws/simple-s3 が必要です。

'bootstrap' => true でプラグインを読み込むと、AsyncAws 設定 (他の機能と同様に Aws 設定も使えます) で ストリームラッパーが登録されます。自分で登録することもできます。

php
App::uses('S3StreamWrapper', 'AsyncAws.Lib');

// With the AsyncAws configuration
S3StreamWrapper::bootstrap();

// Or with a client
S3StreamWrapper::register($this->AsyncAws->createSimpleS3(['region' => 'us-east-1']));

async-aws/simple-s3 がインストールされていない場合、ブートストラップは警告をログに記録し、 ストリームラッパーを登録しません。登録したら、次のように使えます。

php
file_put_contents('s3://my-bucket/reports/today.csv', $csv);
echo file_get_contents('s3://my-bucket/reports/today.csv');

if (is_file('s3://my-bucket/reports/today.csv')) {
    echo filesize('s3://my-bucket/reports/today.csv');
}

// "today.csv", ...
foreach (scandir('s3://my-bucket/reports') as $name) {
    echo $name;
}

S3 オペレーションのオプションは、ストリームコンテキストで渡せます。

php
$context = stream_context_create([
    's3' => [
        'ACL' => 'private',
        'ContentType' => 'text/csv',
        'CacheControl' => 'max-age=3600',
        'Metadata' => ['source' => 'reports'],
        'ServerSideEncryption' => 'AES256',
    ],
]);
file_put_contents('s3://my-bucket/reports/today.csv', $csv, 0, $context);

オプションは AsyncAws のオペレーション (PutObject、GetObject、CopyObject、...) に渡され、 オペレーションは知っているオプションを使います。たとえば、読み込みでは VersionId や Range、 unlink() では VersionId です。次のオプションはストリームラッパー自身が使います。

オプション説明
seekabletrue にすると、読み込みストリームをシーク可能にします (下記を参照)。
delimiteropendir()/scandir() の区切り文字。デフォルト: /。空文字列にすると、プレフィックス以下のすべてのキーを一覧にします。
listFilteropendir() 用の callable。各エントリー (Key、Size、LastModified、... または Prefix) を受け取り、一覧に含めるかどうかを返します。
PartSizeマルチパートアップロードのパートサイズ (MB 単位、デフォルト: 64)。async-aws/simple-s3 3.x では、1 パートより大きなボディはパートに分けてアップロードされます。2.x (PHP 8.1 でインストールされます) は、パートサイズにかかわらず 64 MB までのボディを PutObject でアップロードします。

次の関数をサポートしています。

関数方法
r での fopen()GetObject。ボディはストリーミングされます。
w、x での fopen()データは php://temp バッファーに書き込まれ、ストリームがフラッシュ (fflush()) されるか閉じられたときにアップロードされます。64 MB より大きなボディはパートに分けてアップロードされます。x はオブジェクトが存在する場合 (HeadObject) に失敗します。
a での fopen()オブジェクトがバッファーにダウンロードされ (オブジェクトが存在しない場合、バッファーは空で始まります)、その結果がアップロードされます。
fread()、fwrite()、feof()、ftell()、fseek()、fflush()、fclose()、fstat()ストリームまたはそのバッファーに対して動作します。
file_exists()、is_file()、is_dir()、filesize()、filemtime()、stat()、...HeadObject。キーがオブジェクトでない場合、オブジェクトを持つプレフィックス (ListObjectsV2) はディレクトリです。バケットと s3:// はディレクトリです。ファイルとディレクトリのモードは 0777 です。
unlink()DeleteObject。
rename()CopyObject (メタデータ付き) と DeleteObject。バケット内でもバケット間でも使えます。
copy()オブジェクトを読み込んで書き込みます。
mkdir()s3://bucket はクライアントのリージョンにバケットを作成します。s3://bucket/dir は空の dir/ オブジェクトを作成します。
rmdir()s3://bucket はバケットを削除します。s3://bucket/dir は、そのプレフィックスを持つものが他にない場合に dir/ オブジェクトを削除します。
opendir()、readdir()、rewinddir()、closedir()、scandir()区切り文字を指定した ListObjectsV2 で、ページごとに取得します。dir/ オブジェクトはスキップされます。

制限 ​

次の制限は AWS SDK for PHP のストリームラッパーのもので、このストリームラッパーもそれを引き継いでいます。

  • サポートされるモードは r、w、a、x だけです (r+、w+、c、... はサポートされません)。 そのため、ストリームは読み込みか書き込みのどちらかだけを行います。
  • 読み込みストリーム (r) は、seekable コンテキストオプションが true でない限りシークできません。 true の場合は、読み込んだバイトが php://temp バッファーに保持され、ストリームを前後にシークできます。
  • 書き込みは、書き込んでいる間ではなく、ストリームがフラッシュされるか閉じられたときにアップロードされます。 fflush() のたびにバッファー全体が再度アップロードされます。アップロードのエラーは警告を発生させますが、 fclose() と file_put_contents() はそれを報告できません。重要な場合は fflush() を呼び出し、その結果を確認してください。
  • a はオブジェクト全体をダウンロードし、ストリームが閉じられたときに再度アップロードします。 2 つのプロセスが同時に追記すると、互いの変更を上書きします。
  • touch()、chmod()、chown()、flock() (および LOCK_EX を指定した file_put_contents())、 ftruncate() はサポートされません。
  • ディレクトリはキーのプレフィックスでエミュレートされます。mkdir() は recursive を無視します。 プレフィックスに対する rmdir() はその dir/ オブジェクトだけを削除し、プレフィックスに他のオブジェクトがある場合は失敗します。 プレフィックスにオブジェクトがまったくない場合は true を返します。
  • ACL コンテキストオプションのない mkdir() は、AWS SDK と同様にモードに応じた ACL を送信します。 07xx (デフォルトの 0777 を含む) では public-read、06xx では authenticated-read、それ以外では private です。 オブジェクト所有権の設定が "Bucket owner enforced" のバケット (新しいバケットのデフォルト) は bucket-owner-full-control ACL しか受け付けないため、そのようなバケットではこれを ACL コンテキストオプションで渡してください。
  • rename() は 1 回の CopyObject リクエストでオブジェクトをコピーするため、5 GB までのオブジェクトに限られます (AWS SDK は 5 GB を超えるとマルチパートコピーに切り替えます)。アトミックではなく、コピーの後にコピー元が削除されます。
  • url_stat() の結果と readdir() が一覧にしたエントリーはプロセス内にキャッシュされ (最大 1000 パス)、 ストリームラッパーがパスを変更するとクリアされます。他のプロセスがオブジェクトを変更する場合は S3StreamWrapper::clearCache() を呼び出してください。PHP の clearstatcache() ではこのキャッシュはクリアされません。
  • 読み込みストリームは AsyncAws を通じてボディを受け取ります。AsyncAws は受け取ったバイトのコピーを php://temp ストリームに保持します (2 MB まではメモリ、それを超えると一時ファイル)。
  • エラーは E_USER_WARNING を発生させ、関数は false を返します。file_exists()、is_file() などは、 存在しないパスを警告なしで報告します。
  • ストリームラッパーは STREAM_IS_URL で登録されるため、allow_url_fopen が必要で、 パスをインクルードすること (include 's3://...') はできません。

次の点は AWS SDK と異なります。

  • opendir() はディレクトリを開いたときに最初の ListObjectsV2 リクエストを送信するため、バケットが存在しないと opendir() と scandir() は警告とともに失敗します。後のページでエラーが起きると、readdir() は例外を投げる代わりに 警告とともに false を返します。
  • プレフィックスに対する rmdir() は、プレフィックスに dir/ オブジェクトと他のオブジェクトがある場合にも失敗します (その場合、AWS SDK は dir/ オブジェクトを削除します)。
  • rename() は、ACL (または acl) コンテキストオプションが設定されている場合にだけ ACL を送信します。 AWS SDK は常に ACL (デフォルトでは private) を送信しますが、ACL が無効なバケットは bucket-owner-full-control しか受け付けません。
  • a は、存在しないオブジェクト (404) だけを新しいオブジェクトとして扱います。その他のエラーでは fopen() が失敗します。
  • fstat() はファイルモード 0100777 を返します。
  • async-aws/s3 のクライアント (S3StreamWrapper::register(new S3Client(...))) でのアップロードは、 AWS SDK と同様に PutObject を使い、5 GB までです。async-aws/simple-s3 のクライアント (デフォルト) では、 64 MB (PartSize) より大きなボディはパートに分けてアップロードされます。ContentType が設定されていない場合、 キーのコンテンツタイプは CakePHP の MIME タイプの一覧を使って拡張子から推測されます。

CakePHP の File クラスと Folder クラス ​

CakePHP 2 の File クラスと Folder クラスは、このストリームラッパーでも AWS SDK のものでも、 s3:// パスでは動作しません。Folder::isAbsolute() は、ストリームラッパーのプロトコルが英字だけの場合にしか それを認識しないため、s3://bucket/dir は相対パスとして扱われます。 英字だけのプロトコル、たとえば S3StreamWrapper::register($client, 'awss') を使えば、Folder::read()、find()、 new Folder($path, true) は動作し、File は既存のオブジェクトの読み込み、書き込み、追記、削除ができます。 File::create() が touch() を呼び出すため、File::write() と File::create() ではオブジェクトを作成できません。 オブジェクトの作成には file_put_contents() を使ってください。

S3 ストレージ ​

S3Storage は同じ s3://bucket/key パスを受け取り、 async-aws/simple-s3 を使って一般的なファイル操作を提供します。

php
App::uses('S3Storage', 'AsyncAws.Lib');

$storage = new S3Storage();

$storage->write('s3://my-bucket/reports/today.csv', $csv, ['ContentType' => 'text/csv']);
file_put_contents(TMP . 'today.csv', $storage->read('s3://my-bucket/reports/today.csv'));
メソッド説明
write($path, $contents, $options = [])文字列またはストリームをアップロードします。大きなオブジェクトはパートに分けてアップロードされます。$options は SimpleS3Client::upload() のもので、たとえば ContentType、CacheControl、ACL、Metadata です。
read($path)内容を返します。オブジェクトが存在しない場合は AsyncAws\S3\Exception\NoSuchKeyException を投げます。
readStream($path)内容のストリーム (resource) を返します。
exists($path)オブジェクトが存在するかどうかを返します。
delete($path)オブジェクトを削除します。
url($path)オブジェクトの URL を返します。
presignedUrl($path, $expires = null)署名付きのダウンロード URL を返します。$expires は DateTimeImmutable です。
client()その他の操作のために SimpleS3Client を返します。

new S3Storage() は AsyncAws 設定からクライアントを作成します。別のクライアントを使うには SimpleS3Client を渡します: new S3Storage($this->AsyncAws->createSimpleS3($args))。

著作権とライセンスについては LICENSE を参照してください。Cake Software Foundation とは関係ありません。