アップロードしたファイルの保存のメソッドが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

のようになるわけです。

ファイルをアップロードした後の画面はこんな感じです。
my-application

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-management-console

先の画面に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となります。

By khino