LoginSignup
5
3

エンジニア初心者の投稿であるため、間違っている箇所が多くあるかと思います。
間違っているなどあればご教授いただけると幸いです。

はじめに

laravelを使った画像の受け渡しAPI作成を行なっているときに、『MinIO』と呼ばれるストレージ・サーバーがあることを知りました。調べてみると、『MinIO』はAWSのS3を擬似体験(表現が正しくないかもしれません)をできるということでした。今回は安易に『MinIO』に手を出した初心者の記録を残したいと思います。同じように『MinIO』を使ってみたい方の参考になればと思います。

MinIOとは

openStandiaに書かれているところから引用させていただくと

MinIOは、Go言語で実装されたAmazon S3クラウド・ストレージ・サービスと互換性のあるオブジェクト・ストレージ・サーバーです。
MinIOはAmazon S3と互換性があるため、Amazon S3と全く同じインタフェース(AWS CLIや、AWS SDK)からもアクセスが可能です(ただし一部、MinIOではサポートしていないAPIもあります)。そのため、本番環境ではAmazon S3を使用するが、開発時には、MinIOで開発/テストを行うなどの用途で利用することができます。

簡単にいうと、Amazon S3を擬似体験できる!と解釈しています、私は!

Laravelを使って、MinIOのデータをやり取りする手順

今回説明する方法は実際に実装するにはセキュリティ面で問題が多いです。個人で利用することをお勧めします。

MiniO以外の環境設定

Laravel 9系を使用します。具体的な環境構築が完了している前提で話を進めさせていただきます。
docker環境を用いるので、私が構築の際に利用したサイトを貼っておきます。

MiniOの環境設定

MiniOの環境設定についても以下のものを見るとわかりやすいです。下記のサイト通りに作成をすると利用が可能になります。

この画面が表示できていれば準備万端です。
ここから画像のアップロードと表示を説明します。

スクリーンショット 2024-06-10 23.08.23.png

画像のアップロードと表示

DBの設定

app bash
php artisan make:model Post --migration

今回は特にPost.phpについては変更を加えません。簡易的な作成なためご許しを・・・。
日付_create_posts_table.phpはDBとやり取りをするために変更を加えます。画像を呼び出すために必要なるので必ず設定してください。

日付_create_posts_table.php
return new class extends Migration
{
    /**
     * Run the migrations.
     *
     * @return void
     */
    public function up()
    {
    //変更箇所
        Schema::create('posts', function (Blueprint $table) {
            $table->id();
            $table->string('image');
            $table->timestamps();
        });
    }

    /**
     * Reverse the migrations.
     *
     * @return void
     */
    public function down()
    {
        Schema::dropIfExists('posts');
    }
};

マイグレーションファイルの設定は完了したので、DBに反映させます。

app bash
php artisan migrate

DB内に入って、Postsテーブルができていることを確認してください。
ここまでできていれば用意完璧です。

スクリーンショット 2024-06-10 23.23.30.png

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

簡易的なものであるため、見た目がひどいですが、温かい目で見守ってください。
今回はindex.blade.phpという名前のファイルに作成します。

index.blade.php
<form action="{{ route('upload') }}" method="post" enctype="multipart/form-data">
    {{ csrf_field() }}
    <input type="file" name="file">
    <button type="submit">保存</button>
</form>

<a href="{{ route('show') }}">ここをクリックしてな</a>

ザックリ説明すると、画像を送信するためのformタグがあり、画像を表示する画面へ遷移するaタグがある形になっています。routeの中身である、「update」と「show」は後ほど記述します。

ここで注意してほしい点が一つあります。formタグの属性である【enctype="multipart/form-data"】は忘れずにつけてください。ファイルの送信に利用する属性です。

画像を表示する画面の作成

今回はshow.blade.phpという名前のファイルに作成します。

show.blade.php
<img src="{{ $memo['image'] }}"/>

これだけ!?と思う方がいるかと思いますが、簡易版です。温かい目で…(n回目)。

webファイルの修正(ルーティングの修正)

Viewの部分が完成したので、一度確認の意味を込めてルーティングを設定して、画面に表示できるようにしたいと思います。

web.php
//画像をアップロードする画面のルーティング
Route::get('/', function () {
return view('index');
});

この設定をしたときにこの画面が出てくれば大成功です(私はポートの関係で8088になっています)。

スクリーンショット 2024-06-10 23.48.48.png

controllerの設定

今回のcontroller名はPhotControllerに設定をします。

app bash
php artisan make:controller PhotController

コマンドで作成できたPhotController.phpを編集します。
また、今回はlaravelを用いてMiniOを操作するので、AWS SDKをインストールする必要があります。これをインストールすることで画像の保存を【Storage::disk('s3')】という簡単なコードで行うことができるようになります。

app bash
composer require league/flysystem-aws-s3-v3:^3.0

今回の例ではlaravel 9系の場合でのコマンドです。laravelのバージョンによっては使えない可能性があるので、エラーが発生した場合はまず、依存関係を確かめてください。

PhotController.php
<?php

namespace App\Http\Controllers;

use App\Models\Post;
use Illuminate\Http\Request;
//Storageは呼び出さないと利用ができません
use Illuminate\Support\Facades\Storage;

class PhotController extends Controller
{
    public function upload(Request $request)
    {
        //index.blade.phpのformタグで受け取った画像を変数にいれる
        $file = $request->file('file');

        //この一文だけでMiniOには保存ができます。
        //Storage::disk('s3')->putFile('/', $file, 'public');
        
        //今回はDBにURLを保存するため、先頭に$pathをつけることで画像のパスを変数に代入するとができます
        $path = Storage::disk('s3')->putFile('/', $file, 'public');
        
        //パスからURLに変更しています
        $path = Storage::disk('minio')->url($path);

        //ここについては後述しますが、非常に重要なポイントです。
        $pathArray = explode('/', $path);
        $pathArray[2] = 'localhost:9000';
        $newPathArray = implode('/', $pathArray);

        //DBに画像を開くためのURLを挿入します
        Post::insert([
            'image' => $newPathArray,
        ]);

        //index.blade.phpに戻るための処理です
        return redirect('/');
    }

}

先ほど出てきたこちらのコードについて説明します。長ったらしく、URLを変更していますが意味があります。

PhotController.php
//①パスをそのまま取得している
$path = Storage::disk('minio')->url($path);

//②パスの一部を修正している
$pathArray = explode('/', $path);
$pathArray[2] = 'localhost:9000';
$newPathArray = implode('/', $pathArray);
//①のコードで取得できるパス
http://minio:9000/develop/◯◯.jpg

//②のコードで取得できるパス
http://localhost:9000/develop/◯◯.jpg

見ていただくとわかるように『minio:9000』を『localhost:9000』に変更しています。
これはminioに直接レスポンスが送れない仕様になっているので、docker経由でレスポンスを行っています。
これについてはこちらの記事がわかりやすいです。

実際の実務では一定期間有効なURLを発行することで画像の受け渡しをしており、今回のような受け取り方はよろしくないとのことでした。

画像を表示するためのcontrollerも必要になるため、定義していきます。上記の内容に追加で付け足してください。

PhotController.php
public function show()
{
    //idが1である画像を表示するための記述です。
    $memo = Post::where('id', 1)->first();
    return view('show', compact('memo'));
}

web.phpに追加

controllerの設定ができたので、web.phpにルーティングをしましょう。

web.php
//画像をアップロードする画面のルーティング
Route::get('/', function () {
return view('index');
});

Route::namespace('App\Http\Controllers')->group(function () {
//画像を送信するためのルーティング
    Route::post('/upload', 'PhotController@upload')->name('upload');
//画像を表示する画面のルーティング
    Route::get('/show', 'PhotController@show')->name('show');
});

実際に試してみる

ここまでうまくできていればおそらく画像の受け渡しが可能になっているはずです。実際に画像を使って見てみましょう。

ファイルを選択を押して、画像を挿入する。
スクリーンショット 2024-06-11 15.54.59.png

選択されていませんが画像の名前に変更される。保存をクリック。
スクリーンショット 2024-06-11 15.56.46.png

mysqlのpostsにURLが送信される(idが5になっていますが、初めての方は1になります)。
スクリーンショット 2024-06-11 15.58.56.png

MiniOにアクセスすると画像が増えています。
スクリーンショット 2024-06-11 16.00.45.png

もとの画面に戻って「ここをクリックしてな」をクリック。
スクリーンショット 2024-06-11 15.54.59.png

見事写真が表示されます。
スクリーンショット 2024-06-11 16.04.31.png

おわりに

MiniOを使って簡単な画像の受け渡しを再現しました。今回の実装は自分で遊ぶようのものになっているのでセキュリティ面がガバガバです。実際に実務で使うレベルには程遠いですが、MiniOの使い方を学ぶにはちょうどいい重さの実装でした。AWSはものすごい勢いでアップデートしており、今の方法がいつまで使えるかわかりませんが(現在2024/6/11)サッと試したい方は真似して作ってみてください。

5
3
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
5
3