目次
- AWS EC2に構築したLaravel環境で作成したLaravelアプリから画像ファイルをS3にアップロードする方法をまとめる
実施環境
- ハードウェア環境
項目 | 情報 |
---|---|
OS | macOS Catalina(10.15.5) |
ハードウェア | MacBook Pro (13-inch, 2020, Four Thunderbolt 3 ports) |
プロセッサ | 2 GHz クアッドコアIntel Core i5 |
メモリ | 32 GB 3733 MHz LPDDR4 |
グラフィックス | Intel Iris Plus Graphics 1536 MB |
- ソフトウェア環境(下記の環境をEC2に構築した)
項目 | 情報 | 備考 |
---|---|---|
MySQL | 8.0.20 for Linux on x86_64 | コマンド$ mysql --version で確認 |
Apache | 2.4.43 | コマンド$ httpd --version で確認 |
PHP | 7.4.5 | コマンド$ php --version で確認 |
前提条件
- 下記、または下記に準ずる方法でEC2にLaravelの環境が構築できていること。
読後感
- AWS EC2にてデプロイしたLaravelアプリからのトリガーで画像ファイルをS3の「test」のフォルダ直下に保存することができる。
概要
- S3にてバケットを作成
- アクセスキーの取得
- テーブルの作成
- ファイル設置処理の付与
- 設定
詳細
- 下記の説明で使用するコマンドはsshでインスタンスに接続して実行する物とする。
-
S3にてバケットを作成
- 下記のリンクの手順を実施してS3にバケットを作成する。(testフォルダの作成まで実施する。)
-
アクセスキーの取得
- 下記のリンクの手順を実施してアクセスキーとシークレットアクセスキーの取得を行う。
-
Laravelアプリ側の設定
-
下記コマンドを実行してApacheのドキュメントルートまで移動する。
$ cd /var/www/html/
-
下記コマンドを実行してスワップ領域の値を設定する。(
/bin/dd: failed to open ‘/var/swap.1’: Text file busy
と出力されてしまった方はAWSのEC2コンソールより一旦インスタンスを再起動する。Linuxの物理マシンで実施中の方もLinux物理マシンを再起動する。※インスタンス再起動後はssh接続のコマンドが変化するため注意する。)$ sudo /bin/dd if=/dev/zero of=/var/swap.1 bs=1M count=1024 $ sudo /sbin/mkswap /var/swap.1 $ sudo /sbin/swapon /var/swap.1
-
sshを用いてインスタンスに接続し、下記コマンドを実行してライブラリのインストールを行う。(エラー
The following exception is caused by a lack of memory or swap, or not having swap configured
が発生した方はこちら→composerを用いたインストール中にメモリ系のエラーが出た話)$ cd /var/www/html/test $ composer require league/flysystem-aws-s3-v3 ~1.0
-
下記コマンドを実行してLaravelの設定ファイルを開く。
$ vi .env
-
下記の様に設定ファイルを修正する。
-
修正前
/var/www/html/test/.envAWS_ACCESS_KEY_ID= AWS_SECRET_ACCESS_KEY= AWS_DEFAULT_REGION=us-east-1 AWS_BUCKET=
-
修正後
/var/www/html/test/.envAWS_ACCESS_KEY_ID=AWSのアクセスキーを記載する AWS_SECRET_ACCESS_KEY=AWSのシークレットアクセスキーを記載する AWS_DEFAULT_REGION=ap-northeast-1 AWS_BUCKET=先に作成したバケット名
-
修正後の.envファイルの全体を下記に記載する。
/var/www/html/test/.envAPP_NAME=test APP_ENV=local APP_KEY=base64:ZJYPq8Ij/UIWowQG+H4Gwz+zXjs/vEn85Yfv45qQa88= APP_DEBUG=true APP_URL=http://localhost LOG_CHANNEL=stack DB_CONNECTION=mysql DB_HOST=127.0.0.1 DB_PORT=3306 DB_DATABASE=test DB_USERNAME=root DB_PASSWORD=************** BROADCAST_DRIVER=log CACHE_DRIVER=file QUEUE_CONNECTION=sync SESSION_DRIVER=file SESSION_LIFETIME=120 REDIS_HOST=127.0.0.1 REDIS_PASSWORD=null REDIS_PORT=6379 MAIL_MAILER=smtp MAIL_HOST=smtp.mailtrap.io MAIL_PORT=2525 MAIL_USERNAME=null MAIL_PASSWORD=null MAIL_ENCRYPTION=null MAIL_FROM_ADDRESS=null MAIL_FROM_NAME="${APP_NAME}" AWS_ACCESS_KEY_ID=AWSのアクセスキーを記載する AWS_SECRET_ACCESS_KEY=AWSのシークレットアクセスキーを記載する AWS_DEFAULT_REGION=ap-northeast-1 AWS_BUCKET=先に作成したバケット名 PUSHER_APP_ID= PUSHER_APP_KEY= PUSHER_APP_SECRET= PUSHER_APP_CLUSTER=mt1 MIX_PUSHER_APP_KEY="${PUSHER_APP_KEY}" MIX_PUSHER_APP_CLUSTER="${PUSHER_APP_CLUSTER}"
-
-
-
テーブルの作成
-
アプリ名ディレクトリで下記コマンドを実行してS3に格納する画像ファイルのパスとログイン中のユーザIDを格納するimagesテーブルを作成するマイグレーションファイルとモデルファイルを作成する。
$ php artisan make:model Image --migration
-
下記にファイルが作成された事を確認する。
アプリ名ディレクトリ/app/Image.php
アプリ名ディレクトリ/database/migrations/YYYY_MM_DD_XXXXXX_create_images_table.php
-
アプリ名ディレクトリで下記コマンドを実行してマイグレーションファイルを開く。
$ vi database/migrations/YYYY_MM_DD_XXXXXX_create_images_table.php
-
開いたマイグレーションファイルを下記の様に記載する。
アプリ名ディレクトリ/database/migrations/YYYY_MM_DD_XXXXXX_create_images_table.php<?php use Illuminate\Database\Migrations\Migration; use Illuminate\Database\Schema\Blueprint; use Illuminate\Support\Facades\Schema; class CreateImagesTable extends Migration { /** * Run the migrations. * * @return void */ public function up() { Schema::create('images', function (Blueprint $table) { $table->id(); //下記を追記する $table->foreignId('user_id'); $table->string('path'); //上記までを追記する $table->timestamps(); }); } /** * Reverse the migrations. * * @return void */ public function down() { Schema::dropIfExists('images'); } }
-
アプリ名ディレクトリで下記コマンドを実行してマイグレーションを行う。
$ php artisan migrate
-
-
ファイル設置処理の付与
-
アプリ名ディレクトリで下記コマンドを実行してルーティングファイルを開く。
$ vi routes/web.php
-
開いたルーティングファイルを下記の様に修正する。(そのほかのルーティング情報が下記記載と一致していなくても追記部分だけ追記する。)
アプリ名ディレクトリ/routes/web.php<?php use Illuminate\Support\Facades\Route; /* |-------------------------------------------------------------------------- | Web Routes |-------------------------------------------------------------------------- | | Here is where you can register web routes for your application. These | routes are loaded by the RouteServiceProvider within a group which | contains the "web" middleware group. Now create something great! | */ Route::get('/', function () { return view('welcome'); }); Auth::routes(); Route::get('/home', 'HomeController@index')->name('home'); //下記を追記 //画像ファイルをアップロードするボタンを設置するページへのルーティング Route::get('/upload/image', 'ImageController@input'); //画像ファイルをアップロードする処理のルーティング Route::post('/upload/image', 'ImageController@upload'); //アップロードした画像ファイルを表示するページのルーティング Route::get('/output/image', 'ImageController@output'); //上記までを追記
-
アプリ名ディレクトリで下記コマンドを実行してコントローラファイルを作成する。
$ php artisan make:controller ImageController
-
下記のコントローラファイルが作成される。
アプリ名ディレクトリ/app/Http/Controllers/ImageController.php
-
アプリ名ディレクトリで下記コマンドを実行してコントローラファイルを開く。
$ vi app/Http/Controllers/ImageController.php
-
開いたコントローラファイルを下記の様に修正する。
アプリ名ディレクトリ/app/Http/Controllers/ImageCotroller.php<?php namespace App\Http\Controllers; use Illuminate\Http\Request; //下記を追加する use Illuminate\Support\Facades\Auth; use Illuminate\Support\Facades\Storage; class ImageUploadController extends Controller { //下記を追加 public function input() { return view('images.input'); } public function upload(Request $request) { $this->validate($request, [ 'file' => [ // 必須 'required', // アップロードされたファイルであること 'file', // 画像ファイルであること 'image', // MIMEタイプを指定 'mimes:jpeg,png', ] ]); if ($request->file('file')->isValid([])) { //バリデーションを正常に通過した時の処理 //S3へのファイルアップロード処理の時の情報を変数$upload_infoに格納する $upload_info = Storage::disk('s3')->putFile('/test', $request->file('file'), 'public'); //S3へのファイルアップロード処理の時の情報が格納された変数$upload_infoを用いてアップロードされた画像へのリンクURLを変数$pathに格納する $path = Storage::disk('s3')->url($upload_info); //現在ログイン中のユーザIDを変数$user_idに格納する $user_id = Auth::id(); //モデルファイルのクラスからインスタンスを作成し、オブジェクト変数$new_image_dataに格納する $new_image_data = new Image(); //プロパティ(静的メソッド)user_idに変数$user_idに格納されている内容を格納する $new_image_data->user_id = $user_id; //プロパティ(静的メソッド)に変数$pathに格納されている内容を格納する $new_image_data->path = $path; //インスタンスの内容をDBのテーブルに格納する $new_image_data->save(); return redirect('/'); }else{ //バリデーションではじかれた時の処理 return redirect('/upload/image'); } } public function output() { //現在ログイン中のユーザIDを変数$user_idに格納する $user_id = Auth::id(); //imagesテーブルからuser_idカラムが変数$user_idと一致するレコード情報を取得し変数$user_imagesに格納する $user_images = Image::whereUser_id($user_id)->get(); return view('images.output', ['user_images' => $user_images]); } //上記までを追記 }
-
-
アプリ名ディレクトリで下記コマンドを実行してビューファイルを格納するディレクトリを作成する。
```terminal $ mkdir resources/views/images ```
-
アプリ名ディレクトリで下記コマンドを実行してビューファイルを作成する。
$ touch resources/views/images/input.blade.php $ touch resources/views/images/output.blade.php
-
アプリ名ディレクトリで下記コマンドを実行して画像をアップロードするビューファイルを開く。
$ vi resources/views/images/input.blade.php
-
開いたビューファイルを下記の様に記載する。
アプリ名ディレクトリ/resources/views/images/input.blade.php@extends('layouts.app') @section('content') <!-- トリガー --> <form action="/upload/image" method="POST" enctype="multipart/form-data"> @csrf <label for="photo">画像ファイル:</label> <input type="file" class="form-control" name="file"> <br> <input type="submit"> </form> @endsection
-
アプリ名ディレクトリで下記コマンドを実行して画像をアップロードするビューファイルを開く。
$ vi resources/views/images/output.blade.php
-
開いたビューファイルを下記の様に記載する。
アプリ名ディレクトリ/resources/views/images/output.blade.php@extends('layouts.app') @section('content') <a href="/upload">画像のアップロードに戻る</a> <br> @foreach ($user_images as $user_image) <img src="{{ $user_image['path'] }}"> <br> @endforeach @endsection
-
-
確認
-
ブラウザからAWSの下記のページ(コンソール)にアクセスする。
-
「接続」をクリックする。
-
下記画像の矢印が指しているURLをコピーして別のブラウザのURL入力欄に貼り付ける。
-
下記のページが表示されることを確認する。
-
先に表示したLaravelアプリのホーム画面のURLに
/upload/image
を末尾に追記したURLにアクセスし、先にに作成したファイルを送信するトリガーのボタンが存在するページを表示する。 -
任意の画像ファイルを選択し「送信」ボタンを押下する。(送信ボタン押下後にエラーが403エラーが発生する場合は.envファイルの記載に誤りがあることが多い)
-
S3のバケットのテストファイル直下に下記の様にファイルが格納されていることを確認する。(ファイル名はランダムになる。)
-
先に表示したLaravelアプリのホーム画面のURLに
/output/image
を末尾に追記したURLにアクセスし、先にアップロードした画像が表示されていることを確認する。
-