Hokma School :: Course 2 Laravel
Laravel 09. File Upload
테디아저씨
2026. 5. 8. 09:07

resources/member/myphoto.blade.php
<div class="row mt-5">
<h1>
My Profile
</h1>
</div>
<div class="row mt-2">
<div class="col-md-4">
이름<br/>
<span>{{ $user['name'] }}</span>
</div>
<div class="col-md-8">
<form action="{{ route('myphoto.submit') }}" method="POST" enctype="multipart/form-data">
@csrf
<input type="file" name="photo" class="form-control" accept="image/*">
<button type="submit" class="btn btn-primary mt-2">업로드</button>
</form>
</div>
</div>
Model
php artisan make:migration photo_to_users
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
return new class extends Migration
{
/**
* Run the migrations.
*/
public function up(): void
{
Schema::table('users', function (Blueprint $table) {
//
$table->string('photo')->nullable();
});
}
/**
* Reverse the migrations.
*/
public function down(): void
{
Schema::table('users', function (Blueprint $table) {
//
$table->dropColumn('photo');
});
}
};
routes/web.php
Route::middleware('auth')->group(function () {
Route::get('/dashboard', [IndexController::class, 'dashboard'])->name('dashboard');
Route::get('/myphoto', [UserController::class, 'myphoto'])->name('myphoto');
});
public function myphoto(){
if( Auth::check() ){
$user = Auth::user();
} else {
$user = [];
}
return view('member.myphoto', [ 'user' => $user ]);
}
UserController.php
public function myphoto_submit(Request $request)
{
$photo = $request->file('photo');
dd($photo);
}
dd 로 데이터를 확인하자

파일 저장
라라벨의 스토리지를 직접 접근하지 않습니다.
심볼릭 링크 생성
라라벨은 보안을 위해
php artisan storage:link
Why?
Storage 는 직접접근이 불가능합니다.
Laravel Path
storage/app/public
Web Path
public/storage
config/filesystem.php
'disks' => [
'public' => [
'driver' => 'local',
'root' => storage_path('app/public'),
'url' => env('APP_URL').'/storage',
'visibility' => 'public',
],
]
UserController.php
public function myphoto_submit(Request $request)
{
$request->validate([
'photo' => 'required|image|mimes:jpeg,png,jpg,gif,svg|max:2048',
]);
$photo = $request->file('photo');
// folder, disk
$path = $photo->store('photos', 'public');
// save file
$user = Auth::user();
// update to DB
$user->photo = $path;
$user->save();
return redirect()->route('myphoto')->with('success', 'Photo uploaded successfully');
}
Validation
$request->validate([
'image' => 'required|image|mimes:jpg,png,jpeg|max:2048'
]);
- image → 이미지 파일만
- mimes → 확장자 제한
- max → 용량 제한
파일저장
$path = $photo->store('photos', 'public');
'photos' : saved folder
'public' : used disk
파일확인
File
storage/app/public/images
디비저장
// update to DB
$user->photo = $path;
$user->save();
@if( isset($user) && !empty($user) && isset($user['photo']) && !empty($user['photo']) )
<img src="{{ asset('storage/'.$user['photo']) }}">
@else
<span>No photo</span>
@endif
or
//Controller
$img_url = "";
//view
<img src="{{ asset($img_url) }}">
- 파일명변경
$fileName = time().'_'.$photo->getClientOriginalName();
$path = $photo->storeAs('photos', $fileName, 'public');
기타 다른 파일명사용
$fileName = uniqid().'.'.$file->getClientOriginalName();
// 663ab12cd.test.jpg
$fileName = uniqid().'.'.$file->extension();
// 663ab12cd.jpg
** 주의 : 저장한 파일명을 그대로 디비에 저장
파일삭제
views/member/myphoto.blade.php
@if( isset($user) && !empty($user) && isset($user->photo) && !empty($user->photo) )
<img src="{{ asset('storage/'.$user['photo']) }}" alt="프로필" class="img-thumbnail mb-2 d-block">
<form action="{{ route('myphoto.delete') }}" method="post" class="mb-3">
@csrf
<button type="submit" class="btn btn-danger">삭제</button>
</form>
@else
<span>No photo</span>
@endif
routes/web.php
Route::delete('/myphoto/delete', [UserController::class, 'myphoto_delete'])->name('myphoto.delete');
UserController.php
use Illuminate\Support\Facades\Storage;
...
public function myphoto_delete(Request $request)
{
$user = Auth::user();
if( isset($user) && !empty($user) && isset($user->photo) && !empty($user->photo) ){
Storage::disk('public')->delete($user->photo);
$user = Auth::user();
$user->photo = null;
$user->save();
}
return redirect()->route('myphoto')->with('success', 'Photo deleted successfully');
}
## 과제
1. Truck Image Upload
2. 이미지의 경우 리사이징