いずみこんな悩みを解決できる記事を書きました!
僕は現役フリーランスエンジニア(歴10年)で、資格は13個保有しています。
「Laravelでアップロードしたファイルの保存先や管理方法に迷っている」とお感じではありませんか?
ファイルをどのディレクトリに置くか、ファイル名の重複をどう防ぐかで悩む場面は多いはずです。
Storageファサードを使えば、ローカルでもS3でも同じコードでファイルを保存・取得・削除できます。



フォーム画面のアップロードもAPIのアップロードも、やり方は共通なので順番に解説します。
ということで、本記事ではLaravelでファイルアップロードをStorageで実装する方法を解説します。



すぐ読み終わるので、ぜひ最後までご覧ください。
| 【当サイト】おすすめフリーランスエージェント3選 | |||
|---|---|---|---|
| エージェント | 評価 | ポイント | 公式サイト |
レバテックフリーランス | 5.0 | 業界最大級のエージェント。 高単価案件が豊富。 | 公式 |
Midworks | 4.8 | 満足度調査で 3年連続3冠を達成。 | 公式 |
ITプロパートナーズ | 4.6 | 週2〜3向けの案件が豊富。 | 公式 |
【Laravel】ファイルアップロードをStorageで実装する方法
早速、LaravelでファイルアップロードをStorageで実装する手順を見ていきます。
Storageによるファイル保存の仕組み
LaravelのStorageファサードは、ファイルの保存先を「ディスク」という単位で抽象化します。
ディスクの定義はconfig/filesystems.phpにまとまっていて、localディスク・publicディスク・s3ディスクが最初から用意されています。
localディスクはstorage/app/privateに保存され、ブラウザから直接アクセスできません。
publicディスクはstorage/app/publicに保存され、シンボリックリンク経由でブラウザに公開できます。



ユーザーがダウンロードするファイルはpublicディスク、非公開のファイルはlocalディスク、と使い分けます。
publicディスクを公開する準備
publicディスクに保存したファイルをブラウザから見えるようにするには、シンボリックリンクを作成します。
ターミナルでstorage:linkコマンドを実行します。
php artisan storage:linkpublic/storage から storage/app/public へのリンクが張られます。
保存したファイルには /storage/ファイルパス の形でアクセスできます。
本番環境へデプロイした直後も、storage:linkコマンドの実行が必要になります。
アップロードフォームを用意する
ファイルを送信するフォームには、enctype属性にmultipart/form-dataを指定します。
<form action="/documents" method="POST" enctype="multipart/form-data">
@csrf
<input type="file" name="document">
<button type="submit">アップロード</button>
</form>enctype属性を書き忘れるとファイルがサーバーに届かないので注意します。
バリデーションを設定する
アップロードされたファイルの種類とサイズは、FormRequestで検証します。
php artisan make:request StoreDocumentRequestapp/Http/Requests/StoreDocumentRequest.php が生成されます。
Illuminate\Validation\Rules\FileクラスのtypesメソッドとmaxメソッドでMIMEタイプと最大サイズを指定します。
<?php
namespace App\Http\Requests;
use Illuminate\Foundation\Http\FormRequest;
use Illuminate\Validation\Rules\File;
class StoreDocumentRequest extends FormRequest
{
public function authorize(): bool
{
return true;
}
public function rules(): array
{
return [
'document' => [
'required',
File::types(['pdf', 'jpg', 'png'])->max(5 * 1024),
],
];
}
}maxメソッドの引数はキロバイト単位で、5 * 1024 と書くと5MBになります。



画像だけを許可したいときは File::image() が使えます。
Storageにファイルを保存する
検証を通過したファイルは、storeメソッドまたはstoreAsメソッドで保存します。
storeメソッドは第1引数に保存先ディレクトリ、第2引数にディスク名を受け取ります。
ファイル名はLaravelが自動でユニークな文字列を生成するため、名前の重複を気にする必要がありません。
<?php
namespace App\Http\Controllers;
use App\Http\Requests\StoreDocumentRequest;
use App\Models\Document;
class DocumentController extends Controller
{
public function store(StoreDocumentRequest $request)
{
$path = $request->file('document')->store('documents', 'public');
$document = Document::create([
'path' => $path,
'original_name' => $request->file('document')->getClientOriginalName(),
]);
return redirect()->route('documents.show', $document);
}
}storeメソッドの戻り値は documents/xxxx.pdf のような保存パスです。
戻り値の保存パスをカラムに保存しておくと、後からファイルを取り出せます。
元のファイル名を残したい場合は、getClientOriginalNameメソッドの結果を別カラムに保存します。
ファイル名を自分で決めたいときは storeAs メソッドを使います。
use Illuminate\Support\Str;
$file = $request->file('document');
$path = $file->storeAs(
'documents',
Str::uuid() . '.' . $file->extension(),
'public'
);


ファイル名にユーザーの入力値をそのまま使うと危険なので、UUIDやハッシュ値を使います。
保存したファイルを表示・ダウンロードする
publicディスクのファイルURLは Storage::url メソッドで取得します。
use Illuminate\Support\Facades\Storage;
// ビューで画像を表示する
<img src="{{ Storage::url($document->path) }}">
// ダウンロードダイアログを出す
return Storage::disk('public')->download($document->path, $document->original_name);downloadメソッドの第2引数には、ダウンロード時に表示させたいファイル名を渡します。
不要になったファイルを削除する
レコードを削除するときは、Storageのファイルも合わせて削除します。
use Illuminate\Support\Facades\Storage;
Storage::disk('public')->delete($document->path);
$document->delete();deleteメソッドは対象ファイルが存在しなくてもエラーを投げず、falseを返すだけです。



モデルのdeletingイベントでファイル削除を呼ぶと、消し忘れを防げます。
| 【当サイト】おすすめフリーランスエージェント3選 | |||
|---|---|---|---|
| エージェント | 評価 | ポイント | 公式サイト |
レバテックフリーランス | 5.0 | 業界最大級のエージェント。 高単価案件が豊富。 | 公式 |
Midworks | 4.8 | 満足度調査で 3年連続3冠を達成。 | 公式 |
ITプロパートナーズ | 4.6 | 週2〜3向けの案件が豊富。 | 公式 |
【厳選】フリーランスエンジニアにおすすめなエージェント3選


フリーランスエンジニアになるにはエージェントから案件をもらう必要があります。
僕が実際に利用しているおすすめエージェントを紹介しますね。



エージェントは必ず複数登録してください。
担当者によっては「全然案件紹介してくれない…」みたいなこともあるので…
僕は実際に5つのエージェントを使い回していますよ。
フリーランスを始めるなら「レバテックフリーランス


」
- 業界最大級の案件数。
- 業界トップクラスの高単価報酬、低マージン(平均年収862万円)。
- 案件参画中のフォローの充実。
※詳細は「【業界最大手】レバテックフリーランスとは?メリットや利用手順を解説!」を参照。
レバテックフリーランス
![]()
![]()
とにかく案件数が多いので、とりあえず登録しておけば間違いないエージェントです!



僕もはじめてフリーランスの案件を貰ったのはレバテックフリーランス
![]()
![]()
保有している案件数が多いので、業務経験がなくても何かしらの案件は紹介してもらえますよ(僕はJavaの経験3年でも案件を貰えました)。
手厚い保障を重視したいなら「Midworks


」
- 手厚い保障で正社員並みの安心感。
- 還元率60%超え&単価公開でクリアな契約。
- 給与保障制度(審査あり)。
Midworks
![]()
![]()
フリーランスを目指しているけど不安な方や保障を重視したい方におすすめです。



僕も何度か案件を紹介してもらいました。
自分のスキルに合った案件を紹介してもらえましたし、電話のやり取りも非常に丁寧でした。
週2〜3日の案件探しなら「ITプロパートナーズ


」
- IT案件に特化したフリーランスエージェント。
- 週2〜3日の案件が豊富。
- リモート案件が多く、直エンドなので単価も高い。
※詳細は「【週2・3案件】ITプロパートナーズとは?メリットや利用手順を解説!」を参照。
ITプロパートナーズ
![]()
![]()
週2〜3日から参画できる案件が豊富なので、起業したい人にもおすすめです。



週2〜3日の案件はある程度スキルがないと紹介してもらえない印象です。
とはいえ、週5の案件ももちろんありますし、僕が利用した時は迅速・丁寧に対応していただきました!
よくある質問
storage/app/public と public/storage はどう違いますか?
storage/app/public が実ファイルの保存先です。
public/storage は storage:link コマンドで作られるシンボリックリンクで、Webサーバーの公開ディレクトリから実ファイルへ橋渡しします。
アップロードできるファイルサイズの上限を大きくするには?
PHPの設定値である upload_max_filesize と post_max_size を php.ini で変更します。
Laravel側のバリデーションの max も忘れずに合わせて広げます。
保存先をS3に変えるときコードの修正は必要ですか?
storeメソッドやstoreAsメソッドのディスク名を s3 に変えるだけで動きます。
config/filesystems.php のs3ディスクにバケット名やリージョンを設定し、league/flysystem-aws-s3-v3 パッケージを追加します。
まとめ
今回は、LaravelでファイルアップロードをStorageで実装する方法について解説しました。
以下が本記事のまとめになります。
- おすすめ本
Laravelの勉強なら「PHPフレームワーク Laravel入門 第2版



最後までお読みいただき、ありがとうございました!
| 【当サイト】おすすめフリーランスエージェント3選 | |||
|---|---|---|---|
| エージェント | 評価 | ポイント | 公式サイト |
レバテックフリーランス | 5.0 | 業界最大級のエージェント。 高単価案件が豊富。 | 公式 |
Midworks | 4.8 | 満足度調査で 3年連続3冠を達成。 | 公式 |
ITプロパートナーズ | 4.6 | 週2〜3向けの案件が豊富。 | 公式 |
- クソおすすめ本



海外のエンジニアがどういった思考で働いているかが理解できます。
海外に行く気はないけど海外エンジニアの動向が気になる雑魚エンジニアにおすすめです(本当におすすめな本しか紹介しないのでご安心を)。









