アップロードしたファイルの保存のメソッドがLaravelで5.3で少し変わりました。ここでそれらの情報更新とともに、AmazonのストレージサービスS3にファイルをアップロードする仕方を紹介します。
まず、準備から、
パッケージの追加と設定
コマンドラインで以下の実行が必要です。
composer require league/flysystem-aws-s3-v3 ~1.0
これにより、
config/filesystems.php
の設定ファイルが作成されます。
return [ 'default' => 'local', 'cloud' => 's3', 'disks' => [ 'local' => [ 'driver' => 'local', 'root' => storage_path('app'), ], 'public' => [ 'driver' => 'local', 'root' => storage_path('app/public'), 'visibility' => 'public', ], 's3' => [ 'driver' => 's3', 'key' => 'AWSのキー', 'secret' => '秘密のキー', 'region' => '地域のコード', // 日本なら、ap-northeast-1 'bucket' => 'バケット名' ], ], ];
local
は、使用しているサーバーのストレージのことです。
rootは、Laravelをインストールしたディレクトリのサブディレクトリ、storage/appの場所となります。
public
は、ウェブユーザーにアップロードしたファイルをパブリックに紹介する場所です。
以下の実行で、public/storageが、storage/app/publicにリンクされます
php artisan storage:link
例えば、アップロードされたファイルは、
storage/app/public/mario.jpg
に保存され、
http://localhost/public/storage/mario.jp
で閲覧できるということです。
s3
のkey, secret, region, bucketの指定は必須です。これらは、Amazonのウェブサービスのコンソールで取得できます。
これで設定終わりです。
ファイルのアップロードのプログラム
簡単なファイルのアップロードのプログラムを書いてみます。
まず、routeの設定から、
Route::get('upload', 'UploadController@create'); Route::post('upload', 'UploadController@store');
これで、
http://localhost/upload
にアクセス可能です。
次にコントローラ、
namespace App\Http\Controllers; use Illuminate\Http\Request; use Storage; class UploadController extends Controller { public function create() { return view('upload'); } public function store(Request $request) { $filename = $request->file('image')->getClientOriginalName(); //アップロードしたファイル名を取得 $path = $request->file('image')->storeAs('public', $filename); return back()->with('filename' => $filename); } }
storeAs('public', $filename);
この最初のパラメータは、ファイルを保存するディレクトリ名です。先のconfig/filesystems.phpの設定で、storage/appがルートのディレクトリゆえに、上のコードではstorage/app/publicにファイルが保存されることになります。
ファイル名がmario.jpgであれば、
storage/app/public/mario.jpg
と保存されます。
ファイルをアップロードするフォームのブレードは、
@extends('layouts.app') @section('content') <div class="container"> <div class="row"> <div class="col-md-8 col-md-offset-2"> <div class="panel panel-default"> <div class="panel-heading">Media Upload</div> <div class="panel-body"> <form class="form-horizontal" role="form" method="POST" action="{{ url('upload') }}" enctype="multipart/form-data"> {{ csrf_field() }} <div class="form-group"> <label for="image" class="col-md-4 control-label">File</label> <div class="col-md-6"> <input id="image" type="file" name="image"> </div> </div> <div class="form-group"> <div class="col-md-6 col-md-offset-4"> <button type="submit" class="btn btn-primary"> Upload </button> </div> </div> </form> </div> </div> </div> </div> <div class="row"> <div class="col-md-8 col-md-offset-2"> <div class="panel panel-default"> <div class="panel-body"> @if (session('filename')) <h4>Local</h4> <img src="{!! asset('storage/'.session('filename')) !!}"> @endif </div> </div> </div> </div> </div> @endsection
先の例で、ファイル名が、mario.jpgならば、
asset('storage/'.session('filename'))
は、
http://localhost/public/storage/mario.jpg
のようになるわけです。
ファイルをアップロードした後の画面はこんな感じです。
S3に画像をアップロード
さて、サーバーにアップした画像を、今度はS3にアップするのですが、これはconfig/filesystems.phpの設定が済んでいれば、本当に簡単です。
コントローラのstore
メソッドにたったの2行追加するだけです。
public function store(Request $request) { $filename = $request->file('image')->getClientOriginalName(); $path = $request->file('image')->storeAs('public', $filename); $contents = Storage::get('public/'.$filename); //ファイルを読み取る Storage::disk('s3')->put($filename, $contents, 'public'); // S3にアップ return back()->with(['filename' => $filename]); }
>put($filename, $contents, 'public')
ここのpublicに注意してください。これがないと一般には公開されません。
以下のAWSのコンソールの赤箱の部分がそれにより追加されます。
先の画面にS3から直接画像を表示したいなら、ブレードに以下の変更を。
<div class="panel-body"> @if (session('filename')) <h4>Local</h4> <img src="{!! asset('storage/'.session('filename')) !!}"> <h4>S3</h4> <img src="{!! Storage::disk('s3')->url(session('filename')) !!}"> @endif </div>
S3の以下のURLが生成されます。
https://s3-us-west-2.amazonaws.com/demo53/mario.jpg
us-west-2
は、設定に使用した地域コードです。日本ならap-northeast-1
となります。