Fitur upload file adalah salah satu kebutuhan umum dalam aplikasi web. Laravel menyediakan cara yang mudah dan aman untuk menangani upload file, termasuk upload banyak file sekaligus. Dalam tutorial ini, kamu akan belajar cara membuat fitur upload multiple file di Laravel dari awal, lengkap dengan validasi dan penyimpanan ke storage.
Persiapan Storage
Laravel menggunakan sistem filesystem untuk mengelola file. Pertama, pastikan kamu sudah membuat symbolic link agar file yang diupload bisa diakses publik:
php artisan storage:link
Perintah ini membuat link dari public/storage ke storage/app/public. File yang disimpan di storage/app/public/ akan bisa diakses via URL.
Membuat Migration dan Model
Buat tabel untuk menyimpan data file yang diupload:
php artisan make:model UploadedFile -m
Edit file migration:
public function up(): void
{
Schema::create('uploaded_files', function (Blueprint $table) {
$table->id();
$table->string('original_name');
$table->string('stored_name');
$table->string('path');
$table->string('mime_type');
$table->unsignedBigInteger('size');
$table->timestamps();
});
}
Edit model app/Models/UploadedFile.php:
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Model;
class UploadedFile extends Model
{
protected $fillable = [
'original_name',
'stored_name',
'path',
'mime_type',
'size',
];
}
Jalankan migration:
php artisan migrate
Membuat Form HTML
Buat view untuk form upload. Perhatikan atribut multiple dan enctype:
<!-- resources/views/upload/index.blade.php -->
<form action="{{ route('upload.store') }}" method="POST" enctype="multipart/form-data">
@csrf
<div>
<label for="files">Pilih File (bisa lebih dari satu):</label>
<input type="file" name="files[]" id="files" multiple accept="image/*,.pdf,.doc,.docx">
@error('files.*')
<p style="color:red">{{ $message }}</p>
@enderror
</div>
<button type="submit">Upload</button>
</form>
Kunci penting: nama input harus files[] (dengan tanda kurung siku) agar PHP mengenalinya sebagai array.
Membuat Controller
php artisan make:controller UploadController
Edit app/Http/Controllers/UploadController.php:
<?php
namespace App\Http\Controllers;
use App\Models\UploadedFile;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Storage;
class UploadController extends Controller
{
public function index()
{
$files = UploadedFile::latest()->get();
return view('upload.index', compact('files'));
}
public function store(Request $request)
{
$request->validate([
'files' => 'required|array|min:1|max:10',
'files.*' => 'file|mimes:jpeg,png,jpg,gif,pdf,doc,docx|max:2048',
]);
$uploadedFiles = [];
foreach ($request->file('files') as $file) {
// Simpan ke storage/app/public/uploads
$path = $file->store('uploads', 'public');
$uploadedFiles[] = UploadedFile::create([
'original_name' => $file->getClientOriginalName(),
'stored_name' => basename($path),
'path' => $path,
'mime_type' => $file->getMimeType(),
'size' => $file->getSize(),
]);
}
return redirect()->route('upload.index')
->with('success', count($uploadedFiles) . ' file berhasil diupload.');
}
public function destroy(UploadedFile $uploadedFile)
{
// Hapus file dari storage
Storage::disk('public')->delete($uploadedFile->path);
$uploadedFile->delete();
return redirect()->route('upload.index')
->with('success', 'File berhasil dihapus.');
}
}
Mendefinisikan Route
// routes/web.php
use App\Http\Controllers\UploadController;
Route::get('/upload', [UploadController::class, 'index'])->name('upload.index');
Route::post('/upload', [UploadController::class, 'store'])->name('upload.store');
Route::delete('/upload/{uploadedFile}', [UploadController::class, 'destroy'])->name('upload.destroy');
Menampilkan File yang Diupload
Tambahkan bagian ini di view untuk menampilkan daftar file:
@if(session('success'))
<p style="color:green">{{ session('success') }}</p>
@endif
<ul>
@foreach($files as $file)
<li>
@if(str_starts_with($file->mime_type, 'image/'))
<img src="{{ Storage::url($file->path) }}" width="100">
@endif
{{ $file->original_name }}
({{ number_format($file->size / 1024, 2) }} KB)
<form action="{{ route('upload.destroy', $file) }}" method="POST" style="display:inline">
@csrf @method('DELETE')
<button type="submit">Hapus</button>
</form>
</li>
@endforeach
</ul>
Tips Keamanan Upload File
- Selalu validasi tipe file dengan
mimesdan batasi ukuran denganmax. - Gunakan nama file acak yang dihasilkan Laravel, bukan nama asli dari user.
- Jangan simpan file executable di folder yang bisa diakses publik.
- Atur batas
upload_max_filesizedanpost_max_sizediphp.inisesuai kebutuhan.
Kesimpulan
Membuat fitur upload multiple file di Laravel cukup mudah berkat helper bawaan seperti $request->file(), store(), dan sistem Storage. Dengan validasi yang tepat dan penyimpanan yang aman, fitur upload kamu sudah siap digunakan di production. Kamu bisa mengembangkannya lebih lanjut dengan menambahkan progress bar upload menggunakan JavaScript atau integrasi dengan layanan cloud seperti AWS S3.