Fitur upload dan download file merupakan fitur umum yang biasa kita temukan di aplikasi. Dengan menggunakan framework laravel, kita bisa dengan mudah mengembangkan fitur untuk mengupload pdf, gambar atau jenis file yang lainnya. Begitu pun dengan fitur untuk download, kita bisa dengan mudah menambahkan fitur tersebut. Di edisi tutorial laravel kali ini kita akan coba membuat dua fitur tersebut, yaitu fitur upload file dan download file.
Pada tutorial laravel ini kita akan membuat sebuah project sederhana, di mana project sederhana ini memiliki fitur untuk mengupload file, download file dan juga menampilkan daftar file yang berhasil kita upload.
Untuk fitur upload file, kita akan coba membatasi hanya file pdf dan docx saja yang bisa kita upload. Jadi di sini kita akan menerapkan validasi form untuk proses upload dengan mengecek tipe file yang diupload. Selain itu kita juga akan mengimplementasikan hasil belajar CRUD laravel 11, yaitu menyimpan data file yang diupload dan menampilkan di daftar file yang telah diupload.
Untuk fitur download file, kita akan coba menggunakan kembali nama original file sebagai nama file yang didownload.
Pertama kita buat project laravel baru menggunakan composer. Sekarang kita buka terminal, lalu kita run command berikut ini.
composer create-project --prefer-dist laravel/laravel upload-download-example
Tunggu sampai proses install laravel selesai.
Selanjutnya kita atur konfigurasi database. Buka file .env
, lalu sesuaikan menjadi seperti berikut ini.
DB_CONNECTION=mysql
DB_HOST=127.0.0.1
DB_PORT=3306
DB_DATABASE=db_belajar_laravel
DB_USERNAME=root
DB_PASSWORD=password
Seperti yang terlihat pada baris kode di atas, koneksi database yang kita gunakan adalah mysql
. Untuk username dan password database sesuaikan dengan credentials mysql yang sudah teman-teman setting. Sedangkan nama database project bisa diisi bebas, sebagai contoh di sini kita gunakan nama db_belajar_laravel
.
Jangan lupa save kembali file .env
.
Karena project kita berhubungan dengan file, kita akan buat table dengan nama files
. Selanjutnya kita buat file model dan migration untuk table files
. Buka kembali terminal, lalu run command berikut ini.
php artisan make:model File -m
Output:
INFO Model [app/Models/File.php] created successfully.
INFO Migration [database/migrations/2024_04_26_071942_create_files_table.php] created successfully.
File model dan migration berhasil kita generate. Sekarang buka file migration database/migrations/2024_xx_xx_xxxxxx_create_files_table.php
di code editor, lalu modifikasi method up()
.
public function up(): void
{
Schema::create('files', function (Blueprint $table) {
$table->id();
$table->string('original_name');
$table->string('generated_name');
$table->timestamps();
});
}
Setelah selesai, save kembali file migration.
Pada baris kode di atas, kita bisa lihat terdapat field original_name
dan generated_name
. Seperti yang sudah disebutkan sebelumnya, kita akan gunakan nama original file ketika file didownload. Jadi kita tambahkan field original_name
untuk menyimpan nama file yang diupload. Sedangkan untuk file yang disimpan distorage, kita akan simpan nama yang sudah dihash dan kita simpan di field generated_name
.
Selanjutnya kita run command migration.
php artisan migrate
Apabila database belum kita buat, akan tampil warning yang ditampilkan di output terminal.
WARN The database 'db_belajar_laravel' does not exist on the 'mysql' connection.
┌ Would you like to create it? ────────────────────────────────┐
│ ● Yes / ○ No │
└──────────────────────────────────────────────────────────────┘
Di sini kita bisa buat database baru melalui command migration. Untuk membuat database baru, pilih Yes, lalu tekan enter untuk melanjutkan.
Output di terminal:
WARN The database 'db_belajar_laravel' does not exist on the 'mysql' connection.
┌ Would you like to create it? ────────────────────────────────┐
│ Yes │
└──────────────────────────────────────────────────────────────┘
INFO Preparing database.
Creating migration table ...................................... 53.83ms DONE
INFO Running migrations.
0001_01_01_000000_create_users_table .......................... 79.62ms DONE
0001_01_01_000001_create_cache_table .......................... 33.49ms DONE
0001_01_01_000002_create_jobs_table ........................... 61.35ms DONE
2024_04_26_032944_create_files_table .......................... 15.68ms DONE
Database dan juga table sudah kita buat menggunakan migration command.
Selanjutnya kita akan modifikasi file app/Models/File.php
untuk menambahkan pengaturan mass assignment.
Sekarang kita buka file app/Models/File.php
, lalu kita tambahkan $fillable
properti untuk mengijinkan mass assignment ketika nanti kita tambahkan data baru.
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
class File extends Model
{
use HasFactory;
protected $fillable = [
'original_name',
'generated_name'
];
}
Save kembali file app/Models/File.php
.
Untuk menambahkan fitur baru, kita buat terlebih dahulu controller untuk menangani fitur-fitur tersebut. Buka kembali terminal, lalu run command berikut ini untuk membuat controller baru.
php artisan make:controller FileController --model=File --resource
Output di terminal:
INFO Controller [app/Http/Controllers/FileController.php] created successfully.
Fitur pertama yang akan kita tambahkan adalah fitur untuk menampilkan daftar file yang terupload. Sekarang kita buka file app/Http/Controllers/FileController.php
di code editor, lalu modifikasi method index()
.
<?php
namespace App\Http\Controllers;
use App\Models\File;
use Illuminate\Http\Request;
class FileController extends Controller
{
public function index()
{
$files = File::latest()->paginate(10);
return view('files.index', compact('files'));
}
// baris kode lainnya
}
Save kembali file app/Http/Controllers/FileController.php
.
Method index()
pada baris kode di atas kita gunakan sebagai method yang menangani permintaan untuk menampilkan halaman indeks atau daftar file. Di dalam method ini, kita menggunakan model App\Models\File
untuk mengambil daftar file dari database, mengurutkannya berdasarkan tanggal terbaru, dan membaginya menjadi beberapa halaman (paginate). Kemudian, kita memasukkan daftar file tersebut ke dalam view files.index
menggunakan method view(). Keyword compact('files')
digunakan untuk mengirimkan variabel $files
ke view dengan nama yang sama.
Selanjutnya kita buat file view baru, yaitu resources/views/files/index.blade.php
. Lalu kita coding baris kode berikut ini.
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>File Management - qadrlabs.com</title>
<link href="https://cdn.jsdelivr.net/npm/[email protected]/dist/css/bootstrap.min.css" rel="stylesheet">
</head>
<body>
<div class="container mt-5">
<div class="row">
<div class="col-md-12">
<div>
<h4 class="text-center my-4">Tutorial Laravel 11: Upload dan Download File @ <a href="https://qadrlabs.com">qadrlabs.com</a></h4>
</div>
<div class="card rounded">
<div class="card-body">
<a href="{{ route('files.create') }}" class="btn btn-md btn-primary mb-3 float-end">Upload File</a>
<table class="table table-bordered">
<thead>
<tr>
<th scope="col">Nama File</th>
<th scope="col" style="width: 20%">Action</th>
</tr>
</thead>
<tbody>
@forelse ($files as $file)
<tr>
<td>{{ $file->original_name }}</td>
<td class="text-center">
<a href="{{ route('files.download', $file) }}" class="btn btn-sm btn-primary">Download</a>
</td>
</tr>
@empty
<tr>
<td colspan="2" class="text-muted text-center">Data file belum tersedia</td>
</tr>
@endforelse
</tbody>
</table>
{{ $files->links() }}
</div>
</div>
</div>
</div>
</div>
<script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/js/bootstrap.bundle.min.js"></script>
</body>
</html>
Setelah selesai save kembali file resources/views/files/index.blade.php
.
Selanjutnya kita akan menambahkan fitur untuk upload file. Buka kembali file controller app/Http/Controllers/FileController.php
, lalu kita modifikasi method create()
.
<?php
namespace App\Http\Controllers;
use App\Models\File;
use Illuminate\Http\Request;
class FileController extends Controller
{
// baris kode lainnya
public function create()
{
return view('files.create');
}
// baris kode lainnya
}
Method create()
kita gunakan sebagai method yang menangani request untuk menampilkan form upload file baru.
Selanjutnya kita buat file view baru, yaitu resources/views/files/create.blade.php
. Di sini kita tambahkan form untuk upload file.
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Upload File Baru - qadrlabs.com</title>
<link href="https://cdn.jsdelivr.net/npm/[email protected]/dist/css/bootstrap.min.css" rel="stylesheet">
</head>
<body>
<div class="container mt-5">
<div class="row">
<div class="col-md-12">
<div>
<h4 class="text-center my-4">Tutorial Laravel 11: Upload dan Download File @ <a href="https://qadrlabs.com">qadrlabs.com</a></h4>
</div>
<a href="{{ route('files.index') }}" class="btn btn-md btn-link mb-3">Back</a>
<div class="card rounded">
<div class="card-body">
<form action="{{ route('files.store') }}" method="POST" enctype="multipart/form-data">
@csrf
<div class="form-group mb-3">
<label class="font-weight-bold">File</label>
<input type="file" class="form-control @error('file') is-invalid @enderror" name="file">
<!-- error message untuk image -->
@error('file')
<div class="alert alert-danger mt-2">
{{ $message }}
</div>
@enderror
</div>
<button type="submit" class="btn btn-md btn-primary me-3">Upload</button>
</form>
</div>
</div>
</div>
</div>
</div>
<script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/js/bootstrap.bundle.min.js"></script>
</body>
</html>
Save kembali file view resources/views/files/create.blade.php
.
Selanjutnya kita modifikasi method store()
di app/Http/Controllers/FileController.php
untuk menangani proses upload file.
<?php
namespace App\Http\Controllers;
use App\Models\File;
use Illuminate\Http\Request;
class FileController extends Controller
{
// baris kode lainnya
public function store(Request $request)
{
$request->validate([
'file' => 'required|mimes:docx,pdf|max:2048'
]);
$file = $request->file('file');
$fileName = $file->hashName();
$file->storeAs('uploads', $fileName);
File::create([
'original_name' => $file->getClientOriginalName(),
'generated_name' => $fileName
]);
return redirect()
->route('files.index')
->with('success', 'File berhasil diupload');
}
// baris kode lainnya
}
Pada baris kode di atas, method store()
adalah method yang menangani proses penyimpanan (upload) file yang dikirim melalui form upload. Di dalam method ini, kita melakukan validasi terhadap input yang diterima menggunakan method validate()
untuk memastikan bahwa file yang diunggah memenuhi persyaratan yang ditentukan, yaitu pdf
dan docx
. Setelah itu, kita mengambil file yang diupload dari request menggunakan $request->file('file')
. Kemudian, kita tentukan nama file yang akan disimpan menggunakan hashName()
untuk memastikan bahwa nama file yang diupload unik. Selanjutnya, kita menyimpan file tersebut ke dalam storage yang telah ditentukan menggunakan storeAs()
. Setelah file berhasil disimpan, kita membuat entri baru dalam tabel files
dengan menggunakan model File
dan method create()
. Terakhir, kita mengarahkan pengguna kembali ke halaman indeks file (files.index
) dengan pesan notifikasi bahwa file berhasil diupload menggunakan redirect()->route()->with()
.
Untuk menambahkan fitur download file, buka kembali file controller app/Http/Controllers/FileController.php
. Kemudian kita tambahkan method baru download()
yang menangani proses download file yang telah kita upload sebelumnya.
<?php
namespace App\Http\Controllers;
use App\Models\File;
use Illuminate\Http\Request;
class FileController extends Controller
{
//baris kode lainnya
public function download(File $file)
{
$filePath = storage_path("app/uploads/{$file->generated_name}");
if (file_exists($filePath)) {
return response()->download($filePath, $file->original_name);
} else {
abort(404, 'File not found');
}
}
}
Apabila telah selesai, save kembali file controller.
Pada baris kode di atas, method download()
adalah method yang menangani request untuk download file dari storage. Method ini menerima parameter $file
yang merupakan instance dari model App\Models\File
. Di dalam method ini, kita gunakan path lengkap ke file yang akan didownload menggunakan storage_path()
. Kemudian, kita melakukan pengecekan apakah file yang dimaksud ada di lokasi yang ditentukan. Jika file tersebut ada, kita menggunakan response()->download()
untuk mengirimkan file tersebut ke pengguna dengan nama file asli ($file->original_name
). Jika file tidak ditemukan, kita menampilkan halaman error 404 dengan menggunakan abort()
.
Coding fitur utama telah selesai, langkah selanjutnya adalah mendefinisikan beberapa route baru.
Buka file routes/web.php
, lalu kita definisikan beberapa route baru.
<?php
use Illuminate\Support\Facades\Route;
Route::get('/', function () {
return view('welcome');
});
// tambahkan route baru
Route::get('/files', [App\Http\Controllers\FileController::class, 'index'])
->name('files.index');
Route::get('/files/create', [App\Http\Controllers\FileController::class, 'create'])
->name('files.create');
Route::post('/files/store', [App\Http\Controllers\FileController::class, 'store'])
->name('files.store');
Route::get('/files/{file}/download', [App\Http\Controllers\FileController::class, 'download'])
->name('files.download');
Save kembali file routes/web.php
.
Untuk uji coba, kita run terlebih dahulu project kita.
php artisan serve
Setelah itu kita akses http://127.0.0.1:8000/files
di browser. Di sini kita bisa lihat halaman daftar file yang nantinya kita upload.
Selanjutnya kita klik button Upload File, untuk masuk ke halaman upload file.
Kita coba pilih sample file untuk kita upload, kemudian kita klik button Upload untuk memulai proses upload.
Kita bisa lihat ada file baru yang berhasil kita upload.
Sekarang kita klik button download, untuk download file yang sudah kita upload sebelumnya. Akan muncul popup untuk memilih lokasi untuk menyimpan file yang akan kita download.
Kita bisa lihat file berhasil kita download dengan nama original file.
Pada tutorial laravel ini kita sudah coba kembangkan project sederhana dengan fitur untuk mengupload file, download file dan menampilkan daftar file yang telah diupload. Pada proses upload file kita implementasikan form validation untuk membatasi tipe data tertentu saja yang dapat diupload. Selain itu kita juga sudah coba mengimplementasikan hasil belajar CRUD laravel untuk menyimpan data dan juga menampilkan data. Di sini kita simpan nama original file yang kita gunakan sebagai nama file yang akan kita download.
© 2024 qadrLabs . All rights reserved. 000515268