「AWS SDK for PHP v3」を使ったS3へのアップロード・ダウンロード処理
こんにちは。
開発チームのワイルド担当、まんだいです。
ググればいくらでも見つかる、「AWS SDK for PHP」ネタですが、まだv2の記事がたくさんあって、実はコマンド体系も大きく変わっていたりでそのまま写経してもうまく動かずに困っている方!(私です)
今回は、「AWS SDK for PHP v3」を使って、S3へのアップロード、ダウンロードのサンプルをお届けします。
お品書き
AWSの設定編
まず、コードを書き始める前に、AWS側の設定をやります。
S3のバケットを作成する、オプションでセキュリティ的な観点から専用のIAMを設定します。
S3のバケット作成
S3のページから、「バケットを作成する」のボタンから、作成を始めます。
名前とリージョン
バケット名
バケット名は、画面にも載っていますが、「DNS準拠のバケット名を入力する」とあります。
DNS準拠とは、
- 英数字とハイフン、ドットのみで構成する(アンダースコアは使用不可)
- 文字数は3~63文字の間
- ハイフン、ドットで終わらない
- ハイフンとドットがお互いに連続しない(「.-」、「-.」)
- ドットが連続しない(「..」、「...」)
- 先頭文字は英数字のみ
のような感じです。
ドットで文字を区切る場合は、サブドメイン形式を使ってSSL通信すると、SSL証明書の警告が出ます。
ドットはできる限り使わない方向がよいかと思います。
リージョン
リージョンには、データを格納したいリージョンを選択します。
日本国内向けのサービスであれば、「ap-northeast-1」(東京)を選択した方がよいでしょう。
既存のバケットから設定をコピー
設定を他のバケットと同様のものを使う場合は、こちらから選択します。
プロパティの設定
名前とリージョンの設定があれば、ひとまずバケットの作成はできますが、アクセス制御や、バージョン管理、ログ取得などの機能を有効にして、更に賢くS3を使う事もできます。
Versioning
アップロードされたファイルをバージョン管理するようにします。
Logging
アクセス履歴をログに吐き出す設定です。
機能自体は無料で利用できますが、ログファイルはS3内に保管されるため、当然S3のストレージ料金は掛かります。
また、ログを閲覧した場合も、データ転送料金が掛かります。
Tags
請求情報とリンクしたTagを設定する事ができます。
この機能を使って、同じアカウント内に設定されたS3オブジェクトの利用料金を別々の請求書にする事ができます。
アクセス許可の設定
アクセスできるユーザー、また公開範囲の設定ができます。
ユーザーを管理
バケットを操作できるユーザーを設定します。
このユーザーはAWSアカウントに紐付いたユーザーで、IAMで作成する必要があります。
パブリックアクセス許可を管理
全員に読み込みをチェックする場合としては、サイト内の静的ファイルなどを置く場合になります。
個人情報が載っているPDFや、大事なエクセルシートなどを置く予定のバケットに対してはパブリックアクセスの項目にチェックを入れないようにします。
後に出てきますが、期限付きURLを生成する場合、パブリックアクセス許可を設定している必要はありませんので、気にせず進みましょう。
以上で、S3バケットの作成は完了です。
IAMの設定
PHPからアクセスする場合、ソースコードの設定ファイル内にアクセスキーとシークレットキーを書き込む必要があります。
なんでもできるアクセスキーを設定してしまうのはまずいので、今回設定したS3バケットにだけアクセスできるユーザーを作成し、そのユーザーを使ってS3への操作をするようにします。
まずは、IAMのユーザー作成画面を開き、以下のように入力します。
次のステップでアクセス権限を設定しますが、ひとまず何も設定せず、確認画面へ進みます。
「このユーザーにはアクセス権限がありません」という警告が出ますが、無視して「ユーザーの作成」ボタンを押し、作成完了します。
アクセス情報が載ったCSVファイルがメールで送信されます。もしくは画面内のCSVをダウンロードのボタンでダウンロードし、手元に保管しておきます。
続いて、ユーザーリストから、先ほど作成したユーザー名をクリックし、概要ページを表示します。
「インラインポリシーの追加」から、ポリシーを設定していきます。
- AWSサービスにAmazon S3」を選択
- アクションには、GetObject
- AmazonリソースネームにS3バケットのARNの後ろに「/*」を付けたものを記入
- 「ステートメントを追加」ボタンを登録すると、下に追加される
上記の手順を「PutObject」の分も行い、2つのステートメントを追加したのが下の画像になります。
できたら、「次のステップ」ボタンを押し、確認画面へ遷移します。
ポリシー名には分かりやすいよう、適当な名前を付け、ポリシーを確認します(恐らく問題ないですが、ARNの辺りは要チェック)。
ポリシーの検証を押してこのポリシーは有効です。」と出たら、ポリシーの適用を押して完了です。
PHPの下準備
やっとPHPのコードを書く準備が出来ましたが、最後に「AWS SDK for PHP」をインストールしておく必要があります。
今回はcomposerからインストールしましたので、そちらの手順を載せておきます。
まっさらな環境の場合は、普通にinstallを実行すれば、完了です。
composer install aws/aws-sdk-php
既にcomposer経由で色々セットアップが済んだ後の環境の場合は、composer.jsonを修正するとかはせず、requireというサブコマンドがあるので、そちらを利用します。
composer require aws/aws-sdk-php
これで最新のAWS SDK for PHPがインストールされました。
アップロード処理(local → S3)
PHPからS3を操作するには、S3Clientクラスを利用します。
# S3Clientクラスからクライアントオブジェクトを作成するパターン $s3client = new Aws\S3\S3Client([ 'credentials' => [ 'key' => 'your access key', 'secret' => 'your access secret', ], 'region' => 'ap-northeast-1', 'version' => 'latest', ]); # S3Clientクラスのfactory()メソッドからクライアントオブジェクトを作成するパターン $s3client = S3Client::factory([ 'credentials' => [ 'key' => 'your access key', 'secret' => 'your access secret', ], 'region' => 'ap-northeast-1', 'version' => 'latest', ]);
2通りのクライアントオブジェクト作成の方法がありますが、どちらも同じように扱えます。
続いて、アップロードの本処理です。
putObject()メソッドを利用します。
$result = $s3client->putObject([ 'Bucket' => 'your bucket name', 'Key' => 'file key', 'SourceFile' => '/path/to/file', 'ContentType' => mime_content_type('/path/to/file'), ]);
アップロードに成功すると、$resultにAws\Resultクラスが返されます。
ここに作成したS3オブジェクトに関する情報が詰まっています。
ダウンロード処理(S3 → local)
では、今度は逆に、ダウンロードを試してみたいと思います。
まずは、S3クライアントの作成です。
$s3client = new Aws\S3\S3Client([ 'credentials' => [ 'key' => 'your access key', 'secret' => 'your access secret', ], 'region' => 'ap-northeast-1', 'version' => 'latest', ]);
その後、お察しの通り、getObject()メソッドでファイルを取得です。
$result = $s3client->getObject([ 'Bucket' => 'your bucket name', 'Key' => 'bucket key', ]);
ダウンロードに成功すると、$resultにAws\Resultクラスが返されます。
期限付きURLの生成(expired url)
S3では、ダウンロードが設定されたURLを作成する事ができます。
この機能によって、大事なファイルをパブリックで公開することなくダウンロードする事ができるようになります。
ChatWorkでも使われている機能で、チャットグループにアップロードしたファイルは、この仕組みを使ってダウンロードさせるようになっています。
こちらの実装も非常に簡単で、少し手順は変わりますが、同じようにS3clientを経由して行います。
$cmd = $s3client->getCommand('GetObject', [ 'Bucket' => \Config::get('file.s3.bucket'), 'Key' => $file->path, ]); $result = $s3client->createPresignedRequest($cmd, '+30 seconds');
getCommand()メソッドで、処理getObject()の挙動をコマンド化して、createPresignedRequest()メソッドに渡しています。
createPresignedRequest()メソッドの第二引数は、Datetimeクラス、タイムスタンプ、strtotime()関数で解釈できる文字列の3種類で設定が可能です。
また、1週間を越える有効期限は設定できず、最長1週間になります。
有効期限を過ぎたリンクに対してアクセスした場合は、以下のような画面が表示され、オブジェクトにアクセスできないようになっています。
まとめ
AWS SDK for PHPは、導入も簡単ですし、使いやすいクラス体系ですが、バージョンによってメソッドがなかったり、引数が違うなどの差異はどうしても出てきますので、この記事が開発の助けになれば幸いです。
以上です。