画像アップロード(拡張)

2018/03/08

前回、画像アップロードを作成しました。

画像アップロード(基本)

しかしこれだけだと、アップロードする画像にバリデーションをかけていないませんし、いくつかの課題があります。

今回は前回作成したアップロード機能にいくつかの機能(バリデーション)を設定してみます。

また、画像ファイルのパスはフロントの箇所で何回も利用することになるので設定ファイル(Config)に書くようにします。

デモはコチラ (ID:laraweb / PASS:laraweb)

 

改修作業

改修作業として以下の内容を仕様に加えます。

・アップロードできる画像が png 形式だけ → png / jpg / gif 対応
・ファイルの容量制限(1M)
・画像の比率が1:1
・横の長さは最大300pxまで
・画像のパスをConfigファイルに記述

<< 画像保存場所 >>
一時保存 → public_path()/img/upload/tmp/
本版保存 → public_path()/img/upload/{id}/
No image → public_path()/img/upload/no-thum.png

流れ

1)バリデーションの設定
2)画像の保存先のパスをConfigに設定
3)画像形式を判定する関数を作成
4)コントローラの編集
5)動作確認

 

1)バリデーションの設定

アップロードする画像のバリデーションはフォームリクエストに記述します。

フォームリクエストについてわからないかたはこちらをご参照ください。

STEP1.バリデーションについて
STEP2.フォームリクエストについて

仕様に沿って改修するなら以下のような記述になります。

  public function rules()
  {
  return [
  'username'=>'required',
  'thum'=>'required|image|mimes:jpeg,png,jpg,gif|max:1024|dimensions:max_width=300,ratio=1/1',
  ];
  }

  public function messages()
  {
  return [
  "required" => "必須項目です。",
  "image" => "指定されたファイルが画像ではありません。",
  "mines" => "指定された拡張子(PNG/JPG/GIF)ではありません。",
  "max" => "1Mを超えています。",
  "dimensions" => "画像の比率は1:1で横は最大300pxです。",
  ];
  }

 

2)画像の保存先のパスをConfigに設定

画像の保存先のパスをConfigに書きます。

フロントで画像を呼び出すときはこの設定値を参照することになります。

Laravel の configフォルダ内に自分で定義した定数をまとめておくと運用・保守の面で便利になります。

\config以下に fpath.php を作成します。以下のように記述します。

return [
  "tmp" => "/img/upload/tmp/",
  "thum" => "/img/upload/",
  "noimage" => "/img/upload/no-thum.png",
];

 

3)画像形式を判定する関数を作成

アップロードできる画像を png , jpg , gif と対象範囲を広げたので、ビューでの呼び出し時にどの形式でアップロードされたか判定する必要がでてきます。

MVCの書き方に沿って、この処理をモデルに記述します。

 
Model

gif、jpeg、pngどの形式の画像でアップロードされているかの関数をモデル内に作成します。

ファイルのパスは先ほどConfigで設定した定数を呼び出して利用します。

:
  public function pic_thum()
  {
  $fnamebase = \Config::get('fpath.thum').$this->id."/"."thum.";

  if(file_exists(public_path().$fnamebase."gif")){
  return $fnamebase."gif";
  }else if(file_exists(public_path().$fnamebase."png")){
  return $fnamebase."png";
  }else if(file_exists(public_path().$fnamebase."jpg")){
  return $fnamebase."jpg";
  }else if(file_exists(public_path().$fnamebase."jpeg")){
  return $fnamebase."jpeg";
  }else{
  return \Config::get('fpath.noimage');
  }
  }

一応、条件分岐の最後に画像がなかったときの処理(No image)を記述しました。

 
View

ビューでの呼び出しは以下のようになります。

:
  <table class="table table-striped">
  <thead>
  <tr><th scope="col">名前</th><th scope="col">サムネイル</th></tr>
  </thead>
  <tbody>
  @foreach ($uploaders as $uploader)
  <tr>
  <td>{{ $uploader->username }}</td><td><img src="{{$uploader->pic_thum()}}" width="150"/></td>
  </tr>
  @endforeach
  </tbody>
  </table>

 

4)コントローラの作成

基本的にロジックは前回と同じです。画像のパスをConfigファイルに移したのでそこだけ編集します。

 
一覧表示

  public function getIndex()
  {
  $uploaders = \App\Uploader::orderBy('created_at', 'desc')->paginate(5);

  $hash = array(
  'uploaders' => $uploaders,
  );

  return view('uploader.index')->with($hash);
  }

 
確認画面(一時保存)

  public function confirm(\App\Http\Requests\UploaderRequest $req)
  {
  $username = $req->username;
  $thum_name = uniqid("THUM_") . "." . $req->file('thum')->guessExtension(); // TMPファイル名
  $req->file('thum')->move(public_path() . \Config::get('fpath.tmp'), $thum_name);
  $thum = \Config::get('fpath.tmp').$thum_name;

  $hash = array(
  'thum' => $thum,
  'username' => $username,
  );

  return view('uploader.confirm')->with($hash);
  }

 
完了画面(本番保存)

  public function finish(Request $req)
  {

  $uploader = new \App\Uploader;
  $uploader->username = $req->username;
  $uploader->save();

  // get insert id from an eloquent model
  $lastInsertedId = $uploader->id;

  // make a directory and move uploaded image to it
  if (!file_exists(public_path() .\Config::get('fpath.thum') . $lastInsertedId)) {
  mkdir(public_path() . \Config::get('fpath.thum') . $lastInsertedId, 0777);
  }

  // rename
  rename(public_path() . $req->thum, public_path() . \Config::get('fpath.thum') . $lastInsertedId . "/thum." .pathinfo($req->thum, PATHINFO_EXTENSION));

  return view('uploader.finish');
  }

 

5)動作確認

きちんと、バリデーションがかかっているか確認してみます。

 
wbm形式(JPG、GIF、PNG以外)をアップロード

 
1M以上の画像をアップロード

 
150×225の画像をアップロード

画像アップロードのチュートリアルについては以上になります。

本庄マサノリ

仕事で Laravel を使っています。気づいたことや新しい発見など情報を発信していきます。問い合わせはこちら

>> Twitter をフォローする

 

-チュートリアル, 初級