0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

Laravel10でS3の画像を扱う

Last updated at Posted at 2024-06-10

Laravel10でS3に画像をアップロードしたり、S3の画像を表示する処理を書いたのでメモとしてまとめておくことにしました。

S3バケットの用意

バケットを作成します。

バケット名を入力し、パブリックアクセスのチェックを外します。これ以外はデフォルトのままバケットを作成します。
スクリーンショット 2024-06-10 23.43.11.png

IAMの作成

S3を操作するためのIAMユーザーを作成します。ポリシーは必要なものをアタッチすれば大丈夫です。
スクリーンショット 2024-06-10 23.48.04.png

セキュリティ認証情報のタブからアクセスキーを作成しておきます。.csvファイルも念のため保存しておくと良いです。

バケットポリシーの設定

S3のバケットを選択し、アクセス許可のタブを開きます。
バケットポリシーの項目から編集ボタンを押します。
ポリシージェネレーターを使用して作成すると簡単です。こんな感じで入力しました。
スクリーンショット 2024-06-10 23.54.28.png
下のようなポリシーが生成されます。

{
    "Version": "2012-10-17",
    "Id": "policyId xxxx",
    "Statement": [
        {
            "Sid": "xxxxxxxxxx",
            "Effect": "Allow",
            "Principal": {
                "AWS": "IAMユーザーのarn"
            },
            "Action": "s3:*",
            "Resource": "s3バケットのarn"
        }
    ]
}

Laravelの準備

以下のライブラリを使用するのでインストールします。flysystem-aws-s3-v3
composer require league/flysystem-aws-s3-v3

追記します。

/config/filesystems.php
  'cloud' => env('FILESYSTEM_CLOUD', 's3'),
  's3' => [
            'driver' => 's3',
            'key' => env('AWS_ACCESS_KEY_ID'),
            'secret' => env('AWS_SECRET_ACCESS_KEY'),
            'region' => env('AWS_DEFAULT_REGION'),
            'bucket' => env('AWS_BUCKET'),
            'url' => env('AWS_URL'),
            'endpoint' => env('AWS_ENDPOINT'),
    ],

.envにも必要な情報を追記します。

.env
AWS_ACCESS_KEY_ID='IAMユーザーのAccess key ID'
AWS_SECRET_ACCESS_KEY='IAMユーザーのSecret access key'
AWS_DEFAULT_REGION=ap-northeast-1
AWS_BUCKET='作成したバケット名'

コントローラーを作成し以下の処理を記述しておきます。
php artisan make:controller ImageUploadController

    public function showUploadForm()
    {
        return view('/upload');
    }

    public function uploadImage(Request $request)
    {
        $request->validate([
            'image' => 'required|image|mimes:jpeg,png,jpg,gif|max:2048',
        ]);

        $file = $request->file('image');

        $fileName = time() . '.' . $file->getClientOriginalExtension();
        $path = 'images/' . $fileName;

        $result = Storage::disk('s3')->put($path, file_get_contents($file));
        if (!$result) {
            Log::error('File could not be uploaded to S3.');
            return response()->json(['error' => 'File could not be uploaded'], 500);
        }
        // 公開URLを取得
        $url = Storage::disk('s3')->url($path);
        return back()->with('success', 'Image uploaded successfully.')->with('url', $url);
    }

web.phpにroutingも追記します

Route::get('/upload', [ImageUploadController::class, 'showUploadForm']);
Route::post('/upload', [ImageUploadController::class, 'uploadImage'])->name('uploadToS3');

viewも簡単に作成しておきます。

<body>
    @if ($message = Session::get('success'))
        <div>
            <strong>{{ $message }}</strong>
        </div>
        <div>
            <img src="{{ Session::get('url') }}" width="300" />
        </div>
    @endif

    @if (count($errors) > 0)
        <div>
            <strong>Whoops!</strong> There were some problems with your input.
            <ul>
                @foreach ($errors->all() as $error)
                    <li>{{ $error }}</li>
                @endforeach
            </ul>
        </div>
    @endif

    <form action="{{ route('uploadToS3') }}" method="POST" enctype="multipart/form-data">
        @csrf
        <div>
            <input type="file" name="image" />
        </div>
        <div>
            <button type="submit">Upload</button>
        </div>
    </form>
</body>

動作確認

ファイルを選択してアップロードします。Uploadボタンを押すとバケットにimageフォルダが作成され、その中にアップロードした画像を確認できます。

スクリーンショット 2024-06-11 0.03.31.png
スクリーンショット 2024-06-11 0.07.29.png

権限まわりで若干悩みましたが意外と簡単にできました。

0
0
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
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?