プログラミングスクール講師の斉藤です。
今回は、LaravelからAmazon S3に画像ファイルをアップロードする方法について解説いたします。
Amazon S3に関する情報は調べれば多数見つかるのですが、S3について別に詳しくなりたくなくてとりあえず使えればいいというレベルの解説をしているサイトがなかったのでここに残します。
また、記事の最後でGitHubに上げたサンプルプログラムをダウンロードできるようにしておきましたので、よかったらそちらもご参照ください。
やる事の概要
大まかにやる事を先に列挙しておきます。
[st-midasibox title=”AWS” fontawesome=”” bordercolor=”” color=”” bgcolor=”” borderwidth=”” borderradius=”” titleweight=”bold”]
・AWSの管理画面でAmazon S3のバケットを作成する
・バケットのアクセス権限を公開に変更する
[/st-midasibox]
[st-midasibox title=”Laravelプロジェクト” fontawesome=”” bordercolor=”” color=”” bgcolor=”” borderwidth=”” borderradius=”” titleweight=”bold”]
・composerコマンドでflysystem-aws-s3-v3を導入する
・.envファイルにAWSの設定値を設定する
[/st-midasibox]
AWS側の設定
まずはAWS側をいじって、画像ファイルの格納場所を用意します。
Amazon S3でバケットを作成する
Amazon S3でファイルを格納する場所をバケットと呼びます。
初期状態ではバケットは作成されていませんので、AWSの管理画面から作成します。

バケット名、国名(英語に変換したもの)は後ほどLaravel側の設定項目に使用します。
アクセス権限の変更
ここで重要となるのは「アクセス権限」の項目です。
バケットを作成した直後はアクセスが非公開となっており、ここを公開に変更しないと、画像ファイルを格納しても外から見えません。
という訳で、以下変更手順です。
バケット名をクリック
アクセス権限のタブを開く
ブロックパブリックアクセスの編集
一番下のみチェックを外す。
バケットポリシーの設定
バケットポリシーを設定しなくてはいけないのですが、コピペ用コードを置いたのでバケット名だけ変更してご利用ください。
※コピペしてバケット名だけご自身の内容に変更してください。
1 2 3 4 5 6 7 8 9 10 11 12 |
{ "Version": "2012-10-17", "Statement": [ { "Sid": "AddPerm", "Effect": "Allow", "Principal": "*", "Action": "s3:GetObject", "Resource": "arn:aws:s3:::バケット名/*" } ] } |
アクセスキー&シークレットキー
LaravelからS3を使うためには
AWS_ACCESS_KEY_ID
AWS_SECRET_ACCESS_KEY
の情報も必要となります。
これらの取得方法はAWSの公式ページを参照してください。
私もこのページの手順通りやって取得できました。
Laravel側の設定
AWS側の設定が終わったら、次はLaravel側で設定作業を行います。
flysystem-aws-s3-v3を導入
Laravelプロジェクトの直下で下記のコマンドを実行します。
1 |
composer require league/flysystem-aws-s3-v3 ~1.0 |
完了まで数分かかりますのでしばらく放っておいてください。
完了するとfilesystems.phpのdisksにs3の項目が追加されます。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 |
'disks' => [ 'local' => [ 'driver' => 'local', 'root' => storage_path('app'), ], 'public' => [ 'driver' => 'local', 'root' => storage_path('app/public'), 'url' => env('APP_URL').'/storage', 'visibility' => 'public', ], 's3' => [ 'driver' => 's3', 'key' => env('AWS_ACCESS_KEY_ID'), 'secret' => env('AWS_SECRET_ACCESS_KEY'), 'region' => env('AWS_DEFAULT_REGION'), 'bucket' => env('AWS_BUCKET'), 'url' => env('AWS_URL'), ], ], |
.envを編集
.envにAWSの設定項目が追加されているので、ここを埋めます。
1 2 3 4 |
AWS_ACCESS_KEY_ID=[AWSのアクセスキー] AWS_SECRET_ACCESS_KEY=[AWSのシークレットアクセスキー] AWS_DEFAULT_REGION=[AWSで使用している国名] ※バージニア北部であればus-east-1 AWS_BUCKET=[S3で作成したバケット名] |
AWS_DEFAULT_REGIONに設定する値についてはAWSサイトのリージョンエンドポイントをご確認ください。
Herokuで利用するには
Herokuにデプロイして利用する際、.envはデプロイされませんので、configコマンドで項目を追加する必要があります。
$ heroku config:set AWS_ACCESS_KEY_ID=[AWSのアクセスキー]
$ heroku config:set AWS_SECRET_ACCESS_KEY=[AWSのシークレットアクセスキー]
$ heroku config:set AWS_DEFAULT_REGION=[AWSで使用している国名]
$ heroku config:set AWS_BUCKET=[S3で作成したバケット名]
Amazon S3を使用するソースコードの書き方
LaravelからAmazon S3へファイルの格納と参照するコードを解説します。
とは言っても、この時点ですでに面倒な設定が完了しているので、あとは普通にStorageを使うだけです。
Viewファイル
今回のサンプルでは、View側はinputタグでファイルだけ送信するようにしています。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
<!DOCTYPE html> <html lang="ja"> <head> <meta charset="UTF-8"> </head> <body> <form action="/posts" method="post" enctype="multipart/form-data"> @csrf <p> <input type="file" name="datafile"> </p> <p> <input type="submit" value="送信する"> </p> </form> </body> </html> |
Amazon S3に画像ファイルを格納する
Storage::diskでS3を操作する変数を取得。
putメソッドでS3に保存し、保存したファイル名を取得。
画像までのフルパスを得るにはurlメソッドにファイル名を指定するだけです。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 |
/** * Store a newly created resource in storage. * * @param \Illuminate\Http\Request $request * @return \Illuminate\Http\Response */ public function store(Request $request) { // ファイルの存在チェック if ($request->hasFile('datafile')) { $disk = Storage::disk('s3'); // S3にファイルを保存し、保存したファイル名を取得する $fileName = $disk->put('', $request->file('datafile')); // $fileNameには // https://saitobucket3.s3.amazonaws.com/uhgKiZeJXMFhL9Vr7yT7XvlJqonPNx30xbJYoEo0.jpeg // のような画像へのフルパスが格納されている // このフルパスをDBに格納しておくと、画像を表示させるのは簡単になる dd($disk->url($fileName)); } redirect('/'); } |
ダウンロード
今回解説したサンプルプログラムはGitHub上からダウンロードできます。
https://github.com/SadayoshiSaito/amazon_s3_sample2