1. Home
  2. PHP
  3. Laravel
  4. LaravelのFlysystem-aws-s3でAmazon S3と連携しファイル操作を行う

LaravelのFlysystem-aws-s3でAmazon S3と連携しファイル操作を行う

  • 公開日
  • 更新日
  • カテゴリ:Laravel
  • タグ:PHP,Laravel,Flysystem,FileStorage,AmazonS3,cache
LaravelのFlysystem-aws-s3でAmazon S3と連携しファイル操作を行う

Laravel ファイル操作 1. local/public ディスク編 2. Amazon S3 編 3. SFTP 編

今回は、Laravel のファイルストレージ機能である Flysystem を使って Amazon S3 と連携し、ファイルの保存や読み出しなど一連の操作を行います。

Contents

  1. 開発環境
  2. Amazon S3 について
  3. flysystem-aws-s3-v3 導入
  4. 設定ファイル編集
    1. サーバの日時設定について
  5. S3 へのファイルの保存・読み出し
  6. キャッシュ設定(Cache-Control)

開発環境

今回の開発環境は以下の通りです。

  • Linux CentOS 7
  • Apache 2.4
  • PHP 7.1
  • Laravel

Laravel のバージョンに関しては、5.6/5.5/5.4/5.3 にて動作確認済みです。

Laravel のルートディレクトリを「laravel/」とします。

今回の作業には composer を使います。未導入の場合は予めインストール を行ってください。

尚、ファイルストレージについての基礎や、ローカルでのファイル操作を行う場合に関しては、 前回の記事であるlocal/public ディスク編 を参考にしてください。

Amazon S3 について

作業に入る前に、S3 について少し紹介しておきます。

Amazon S3 とは、Amazon Web Service が提供するクラウドストレージサービスです。 Simple Storage Service の、頭文字を取ってS3という名称になっています。

S3 の最も良いところといえば、なんといってもその安さです。 1GB 突っ込んでも 1 ドル 100 円換算で 2.5 円とかそんなレベル。そして容量はもちろん無制限なので、大概のものはここに入れておけば問題なく運用できます。

ファイル取得のレスポンスも早いので、WEB サービスを構築する上では今結構スタンダードになっていると思います。

また、S3 に保存したファイルを非公開扱いにも出来ます。非公開設定のファイルやディレクトリに関しては許可されたアカウント以外からでは扱えないので、データを溜めておいたり、色々な使い方もできます。

flysystem-aws-s3-v3 導入

Laravel のファイルストレージと S3 を連携させるには、専用のパッケージを導入する必要があります。

パッケージは公式でもアナウンスのある league/flysystem-aws-s3-v3 を導入します。

Laravel のルートディレクトリへ移動し、以下の composer コマンドを叩いてインストールを行います。

# composer でパッケージを追加
composer require league/flysystem-aws-s3-v3 ~1.0

インストールが完了したら、composer.json を開いて追加されているかを確認します。

laravel/composer.json
"require": {
    "php": ">=7.0.0",
    "laravel/framework": "5.5.*",
    "laravel/socialite": "^3.0",
    "laravel/tinker": "~1.0",
    "league/flysystem-aws-s3-v3": "~1.0" // ← 追加されている事を確認
},

設定ファイル編集

次に、Laravel と S3 が同期出来るように、アカウント情報を設定します。

まずは、Flysystem の設定ファイルを確認します。ファイルを開くと下の方に以下の記述があります。

laravel/config/filesystems.php
'disks' => [
    's3' => [
        'driver' => 's3',
        'key' => env('AWS_KEY'),
        'secret' => env('AWS_SECRET'),
        'region' => env('AWS_REGION'),
        'bucket' => env('AWS_BUCKET'),
    ],
],

この部分が S3 の設定情報を格納している部分になるのですが、指定されているのがこんな形式になっています。

env('AWS_KEY'),
env('AWS_SECRET'),
env('AWS_REGION'),
env('AWS_BUCKET'),

これは.env ファイルから設定情報を読み取っているメソッドになります。したがって、S3 の設定情報はここに直接記載するのではなく、.env ファイルに記載していきます。

わざわざ.env ファイルに記載するのはセキュリティという観点からですが、もう一方で、そうした方が色々な設定情報が散らばらなくて良いという利点もあります。

それでは.env ファイルに S3 の設定情報を記載します。

laravel/.env
AWS_KEY=[アクセスキー]
AWS_SECRET=[シークレットキー]
AWS_REGION=[リージョン(東京なら ap-northeast-1)]
AWS_BUCKET=[バケット名]

これで基本設定は完了です。

サーバの日時設定について

S3 と連携を行うにあたって一点注意すべき事があります。それは、サーバの日時設定です。

Laravel から S3 を操作する際に、アプリケーション側のの日時設定がきちんと行われていないとエラーになります。

Linux で動かす場合には、date コマンドにて、適切な日時設定が行われているか確認してください。

S3 へのファイルの保存・読み出し

それでは実際に Laravel から S3 へのファイル操作を行っていきます。百聞は一見に如かず、まずは一通りの流れをコントローラに記述しました。

<?php
namespace App\Http\Controllers;

use Storage; // ← (1)

class FlySystemS3Controller extends Controller
{
  public function index()
  {
    $disk = Storage::disk('s3'); // ← (2)

   | $public_path = '/path/to/project_root/public/';
(3)| $img_path = sprintf('%s%s', $public_path, 'test.jpg');
   | $contents = file_get_contents($img_path);

    // S3 にファイルをアップロード(パスはバケットディレクトリを起点として相対パスで記述)
    $disk->put('test/test.jpg', $contents, 'public'); // ← (4)

    // S3の完全URLを得る
    $url = $disk->url('test/test.jpg'); // ← (5)
    // $url → https://s3-REGION.amazonaws.com/BUCKET_NAME/test/test.jpg みたいな完全URLが返る

    // S3上に指定ファイルが存在するか確認
    if($disk->exists('test/test.jpg')) { // ← (6)
      echo'<pre>'; echo 'exists'; echo'</pre>';
    } else {
      echo'<pre>'; echo 'NONE'; echo'</pre>';
    }

    // ファイル取得はget()
    $contents = $disk->get('test/test.jpg'); // ← (7)

   | $put_path = sprintf('%s%s', $public_path, 'test_put.jpg');
(8)| // サーバに保存(ダウンロード)
   | file_put_contents($put_path, $contents);

  }
}

上から説明していきます。

use Storage; // ← (1)

まずは Storage クラスを use します。

$disk = Storage::disk('s3'); // ← (2)

どのディスクを使うかの指定をしています。 S3 と連携させるので、「s3 」を指定しています。

   | $public_path = '/path/to/project_root/public/';
(3)| $img_path = sprintf('%s%s', $public_path, 'test.jpg');
   | $contents = file_get_contents($img_path);

ローカルにある画像のフルパスと画像ファイル名を結合させ、file_get_contents() メソッドで画像ファイルデータを読み込んでいます。

// S3 にファイルをアップロード(パスはバケットディレクトリを起点として相対パスで記述)
$disk->put('test/test.jpg', $contents, 'public'); // ← (4)

ここで put メソッドにて、S3 へファイルをアップロードしています。

put メソッドの引数に関しては以下の通りです。

'test/test.jpg'S3 に保存する階層+ファイル名(新たに命名しても OK) $contents読み込んだファイルデータ 'public'視認性の設定。 S3 では、特に指定なくアップロードしたファイルについては「非公開」となり、外部には公開されません。例えば画像をアップロードして公開するなどの場合には、ここを公開状態にする必要があるので、 その場合には第三引数に「public 」を渡します。逆に、公開したくない場合は第三引数は空で OK です。

// S3 の完全 URL を得る
$url = $disk->url('test/test.jpg'); // ← (5)
// $url → https://s3-REGION.amazonaws.com/BUCKET_NAME/test/test.jpg ← 完全 URL が返る

url メソッドを使うと、S3 に保存したファイルの完全 URL を取得出来ます。

上記の例なら
https://s3-REGION.amazonaws.com/BUCKET_NAME/test/test.jpg
の形で返ってきます。

// S3 上に指定ファイルが存在するか確認
$disk->exists('test/test.jpg') // ← (6)

exists メソッドを使うと、対象のファイルが S3 上に存在するどうかを確認できます。

指定している引数には、バケットディレクトリからの相対パスを指定します。

// ファイル取得は get()
$contents = $disk->get('test/test.jpg'); // ← (7)

get メソッドを使うと、画像データを取得できます。

指定している引数には、バケットディレクトリからの相対パスを指定します。

   | $put_path = sprintf('%s%s', $public_path, 'test_put.jpg');
(8)| // サーバに保存(ダウンロード)
   | file_put_contents($put_path, $contents);

S3 からファイルデータ自体を取り出す時は、get メソッドで S3 から取得した画像データに対して保存先のパス(+保存するファイル名)を設定し、file_put_contents メソッドでローカルに保存しています。

キャッシュ設定(Cache-Control)

アップロード時にキャッシュコントロールを付与したいという場合には設定ファイルに記述する事で設定できます。

laravel/config/filesystems.php
's3_' => [
    'driver' => 's3',
    'key' => env('AWS_KEY'),
    'secret' => env('AWS_SECRET'),
    'region' => env('AWS_REGION'),
    'bucket' => env('AWS_BUCKET'),
    'options' => [
      'CacheControl' => 'max-age=999900'
    ]
]

options プロパティに対して CacheControl を設定する事で、キャッシュ設定を付与する事ができます。

ちなみに、この「options 」で設定できる項目は以下の通りです。

  • ACL
  • CacheControl
  • ContentDisposition
  • ContentEncoding
  • ContentLength
  • ContentType
  • Expires
  • GrantFullControl
  • GrantRead
  • GrantReadACP
  • GrantWriteACP
  • Metadata
  • RequestPayer
  • SSECustomerAlgorithm
  • SSECustomerKey
  • SSECustomerKeyMD5
  • SSEKMSKeyId
  • ServerSideEncryption
  • StorageClass
  • Tagging
  • WebsiteRedirectLocation

まとめ

以上で一連の作業は完了となります。
Storage クラスのメソッドはまだ他にもあるので、公式のページで見てみると良いと思います。

Amazon S3 は容量無制限のストレージに併せて高可用性を兼ね備え、 且つレスポンスも速く表示スピードのボトルネックにもならない非常に優秀なクラウドストレージです。
こういった便利なサービスも上手に使って、優れた WEB アプリケーションを作りだしていきたいですね。

Author

rito

  • Backend Engineer
  • Tokyo, Japan
  • PHP 5 技術者認定上級試験 認定者
  • 統計検定 3 級