Laravel で画像のアップロード・リサイズ処理をする方法

Laravelで画像のアップロードとリサイズを行う方法をご紹介します。
PHPで画像のリサイズをする場合は、php-gdやImagick(ImageMagick)を使いますが、今回はそれらをラップしたIntervention/Imageというライブラリを利用して、画像のリサイズを行います。

ソースコードはGithubにアップしています。

概要

仕様についてざっくりと書くと、以下のように作ります。

仕様

  • アップロードした画像は、public/images/〜 に配置する。
  • 参照する場合は、/images/〜 になる。
  • WordPressのように、アップロード時にリサイズを行い、複数のリサイズ後の画像を保存する。

URL設計

MethodURLAction説明
GET/photos/createPhotosController@createファイルアップロード画面を表示
POST/photosPhotosController@storeファイルアップロード処理

※ public/images とURLが干渉するため、photos にしておきます。

ライブラリのインストールと設定

まず、「intervention/image」ライブラリをcomposerでインストールします。

$ composer require intervention/image

次に、configファイルの設定を変更します。

# config/app.php

# 160行あたりに追加する (providersに追加)
Intervention\Image\ImageServiceProvider::class,

# 210行目あたりに追加する(aliasesに追加)
'Image' => Intervention\Image\Facades\Image::class,

これで intervention/image を利用するための準備は完了です。

あとは、画像をアップロードする場所のpublic/imagesディレクトリを作っておきます。

画像をアップロードする画面を作成

画像のアップロード処理を実装する前に、画像をアップロードするための画面を作成します。

以下のコマンドによりコントローラーを作成します。

$ php artisan make:controller PhotosController

ルーティングに使用するURLとメソッドを登録します。
今回はResourceの内、createとstoreのみを利用します。

# routes/web.php

Route::resource('/photos', 'PhotosController', ['only' => ['create', 'store']]);

では、実際に画面を作成します。
LaravelはデフォルトでCSRF保護の処理が入っているので、フォームにCSRFトークンを埋め込むのを忘れないようにしましょう。

# app\Http\Controllers\PhotosController.php

public function create()
{
    return view('photos.create');
}


# views/photos/create.blade.php
<div>
    <h1>画像のアップロード</h1>

    <form method="post" action="{{ action('PhotosController@store') }}" enctype="multipart/form-data">
        {{ csrf_field() }}

        <fieldset>
            <div>
                <input id="file" type="file" name="image">

                @if ($errors->has('image'))
                    {{ $errors->first('image') }}
                @endif
            </div>
        </fieldset>

        <input type="submit" value="アップロード">
    </form>
</div>

これで画像をアップロードする画面は完成です。
サーバーを起動して、http://localhost:8000/photos/create にアクセスして画面が表示されればOKです。

画像をアップロードとリサイズする処理を実装

いよいよ画像のアップロードとリサイズの処理を実装します。

# app\Http\Controllers\PhotosController.php

public function store(Request $request)
{
  $params = $request->validate([
      'image' => 'required|file|image|max:4000',
  ]);

  $file = $params['image'];

  $image = \Image::make(file_get_contents($file->getRealPath()));
  $image
      ->save(public_path().'/images/'.$file->hashName())
      ->resize(300, 300)
      ->save(public_path().'/images/300-300-'.$file->hashName())
      ->resize(500, 500)
      ->save(public_path().'/images/500-500-'.$file->hashName());

  return redirect('/images/'.$file->hashName());
}

Laravelはリクエストのファイルを、「Illuminate\Http\UploadedFile」クラスのインスタンスで返してくれます。
オリジナル画像 と 300×300・500×500でリサイズした画像を、public/images/〜 に保存する処理となっています。

以上で実装は全て完了です。
実際に、http://localhost:8000/photos/create にアクセスして画像を送信し、public/images/〜 にファイルがアップされていると思います。

この記事と関連している記事