Cara Membuat Fitur Upload File atau Gambar di Laravel dengan Storage

Thumbnail Cara Membuat Fitur Upload File atau Gambar di Laravel dengan Storage

Laravel merupakan salah satu framework PHP yang populer karena kemudahan penggunaannya dan fitur-fiturnya yang lengkap. Salah satu fitur penting yang sering dibutuhkan dalam pengembangan aplikasi web adalah kemampuan untuk mengunggah gambar. Dalam artikel ini, kita akan membahas cara membuat fitur upload file atau gambar di Laravel menggunakan Storage, sebuah sistem manajemen file bawaan Laravel yang powerful. Dengan pendekatan ini, kita dapat menyimpan file secara terorganisir.

Fitur upload gambar yang terintegrasi dengan Storage tidak hanya mempermudah pengelolaan file, tetapi juga memberikan fleksibilitas dalam melakukan validasi, optimasi, dan aksesibilitas data. Tutorial ini akan memberikan panduan langkah demi langkah, mulai dari membuat form upload, memproses file yang diunggah, hingga menyimpan file tersebut di direktori yang ditentukan. Dengan memahami konsep dan implementasi yang dijelaskan, diharapkan dapat membantu untuk menambahkan fitur serupa ke dalam proyek Laravel milikmu.

Berikut adalah langkah-langkah membuat fitur upload gambar di Laravel dengan Storage:

1. Menyiapkan Proyek Laravel untuk Fitur Upload Gambar

Langkah pertama sudah pasti adalah menyiapkan proyek Laravel terlebih dahulu yang akan digunakan untuk menerapkan fitur upload gambar. Sangat direkomendasikan menggunakan proyek baru untuk latihan dengan tujuan mencegah hal-hal yang tidak diinginkan pada proyek utama. Jalankan perintah berikut untuk membuat proyek baru:

composer create-project --prefer-dist laravel/laravel latihan-upload-gambar

Oh iya, pada tutorial ini saya tidak menggunakan database, tapi silahkan hubungkan ke database untuk latihan saja apabila muncul error seperti could not find driver (Connection:...).

Jika kamu menggunakan Laravel 11 seperti saya, terdapat konfigurasi pada file .env yang perlu diubah agar file yang diupload disimpan pada folder public, yaitu:

FILESYSTEM_DISK=public

2. Membuat Symbolic Link untuk Akses File

Kemudian, agar dapat mengakses folder storage melalui URL publik, maka aktifkan terlebih dahulu dengan membuat symbolic link. Jalankan perintah:

php artisan storage:link

Apa saja manfaat dari membuat symbolic link untuk folder storage di Laravel?

  • Mengakses file yang Diunggah Secara Publik 
    Dengan symbolic link ini, file yang disimpan di storage/app/public dapat diakses oleh pengguna melalui URL yang dibangun dari direktori public/storage. Hal ini penting untuk menampilkan file seperti gambar, video, atau dokumen yang sudah diupload.

  • Mengorganisir File dengan Lebih Baik 
    Laravel memisahkan penyimpanan file publik dan privat untuk menjaga keamanan dan kemudahan manajemen. Kita tetap dapat menyimpan file privat di direktori storage/app tanpa mengganggu file yang ingin diakses publik.

  • Meningkatkan Keamanan 
    Dengan symbolic link, file asli tetap berada di dalam direktori storage, sehingga tidak terekspos langsung melalui root web server. Akses ke file publik dilakukan melalui symbolic link yang lebih aman dan terstruktur.

  • Kemudahan Migrasi 
    Struktur penyimpanan Laravel dirancang untuk mendukung skalabilitas. Jika suatu saat perlu memindahkan file ke layanan cloud seperti AWS S3 atau Google Cloud Storage, konfigurasi ini akan tetap konsisten, sehingga mempermudah proses migrasi.

Dengan demikian, perintah php artisan storage:link menjadi langkah penting ketika membangun fitur yang melibatkan penyimpanan file di Laravel, terutama saat file tersebut perlu diakses atau ditampilkan kepada pengguna melalui aplikasi web. Untuk memahami lebih dalam mengenai fitur File Storage yang ada di Laravel, silahkan kunjungi halaman dokumentasi resminya di sini.

3. Membuat Controller untuk Menangani Proses Upload Gambar

Buatlah controller untuk menangani proses upload mulai dari menampilkan form, menangani file gambar yang masuk, hingga menampilkan list file yang telah berhasil diupload. Buat controller dengan perintah:

php artisan make:controller ImageController

Buka file ImageController.php dan sesuaikan dengan kode berikut:

<?php

namespace App\Http\Controllers;

use Illuminate\Http\Request;
use Illuminate\Support\Facades\Storage;

class ImageController extends Controller
{
    public function index() {
        // get semua gambar di direktori images
        $images = Storage::files('images');

        // konversi path file ke URL publik
        $imageUrls = array_map(function ($image) {
            return Storage::url($image);
        }, $images);

        return view('upload', [
            'data' => $imageUrls
        ]);
    }

    public function store(Request $request) {
        // validasi file yang dikirim user
        $request->validate([
            'image' => 'required|file|mimes:png,jpg,webp|max:2048'
        ]);

        $image = $request->file('image'); // mengambil file
        $randomImageName = $image->hashName(); // mengubah nama file menjadi random
        $image->storeAs('images', $randomImageName); // menyimpan file ke folder storage/app/public/images

        return redirect()->back()->with('success', 'Gambar berhasil diupload');
    }
}

Method index() selain berfungsi mengarahkan ke form untuk upload gambar, method tersebut juga akan membawa list path gambar yang telah berhasil diupload dan tersedia untuk publik. Sedangkan method store() bertugas untuk melakukan validasi terhadap input yang dikirim oleh pengguna, menyimpan file ke folder storage, hingga mengarahkan kembali ke halaman semula.

Berbicara mengenai validasi input, baiknya setiap permintaan pengguna yang masuk dicek terlebih dahulu untuk mencegah hal-hal yang tidak sesuai dan mungkin berbahaya, selengkapnya bisa kamu pelajari di artikel Tutorial Laravel: Validasi Input dari Form.

4. Membuat View dan Route untuk Form Upload

Berikutnya adalah membuat view yang berisi form untuk upload file. Untuk mempercepat pengerjaan, saya akan menggunakan framework bootstrap. Berikut adalah kode untuk file view upload.blade.php:

<!doctype html>
<html lang="en">
    <head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <title>Latihan Upload Gambar</title>
    {{-- Bootstrap CSS --}}
    <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-QWTKZyjpPEjISv5WaRU9OFeRpok6YctnYmDr5pNlyT2bRjXh0JMhjY6hW+ALEwIH" crossorigin="anonymous">
    </head>
    <body>
    <div class="container col-lg-6">
        {{-- Form --}}
        <form action="{{ route('upload') }}" method="POST" enctype="multipart/form-data" class="py-5">
            @csrf
            <div class="input-group mb-3">
                <input type="file" class="form-control" aria-describedby="button-addon2" accept=".png,.jpg,.webp" name="image" required>
                <button class="btn btn-outline-primary" type="submit" id="button-addon2">Upload</button>
            </div>

            {{-- Menampilkan pesan sukses upload --}}
            @if (session('success'))
                <div class="alert alert-success">
                    {{ session('success') }}
                </div>
            @endif

            {{-- Menampilkan error validasi --}}
            @if ($errors->any())
                <div class="alert alert-danger">
                    <ul class="my-0">
                        @foreach ($errors->all() as $error)
                            <li>{{ $error }}</li>
                        @endforeach
                    </ul>
                </div>
            @endif
        </form>

        {{-- List gambar yang berhasil diupload --}}
        <h2 class="fs-5 fw-bold">List Gambar:</h2>
        <ol class="list-group list-group-numbered">
            @foreach ($data as $path)
                <li class="list-group-item">
                    <a href="{{ $path }}" target="_blank">
                        {{ basename($path) }}
                    </a>
                </li>
            @endforeach
        </ol>
    </div>

    {{-- Bootstrap JS--}}
    <script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/js/bootstrap.bundle.min.js" integrity="sha384-YvpcrYf0tY3lHB60NNkmXc5s9fDVZLESaAA55NDzOxhy9GkcIdslK1eN7N6jIeHz" crossorigin="anonymous"></script>
    </body>
</html>

Mari kita breakdown beberapa bagian penting yang ada pada kode view di atas.

  • Pertama, tag <form> memiliki atribut action="{{ route('upload') }}". Berfungsi untuk mengatur URL tujuan saat form dikirimkan. Nilai dari route('upload') adalah URL yang dihasilkan berdasarkan rute dengan nama upload di file routes Laravel.

  • Kedua, atribut method="POST" berfungsi menentukan metode HTTP yang digunakan untuk mengirim data. POST digunakan untuk mengirimkan data form ke server, terutama jika data bersifat sensitif atau melibatkan perubahan pada server (seperti file upload).

  • Ketiga, atribut enctype="multipart/form-data" adalah atribut wajib yang digunakan saat form berisi input file (<input type="file">). Tanpa atribut ini, data file tidak akan dikirimkan dengan benar ke server. Format ini memastikan data file dikodekan dalam format multipart agar bisa diterima oleh server.

  • Keempat, pada tag <input> terdapat atribut type="file" yang berguna untuk enentukan bahwa input ini digunakan untuk memilih file dari perangkat pengguna.

  • Kelima, terdapat atribut accept=".png,.jpg,.webp" pada tag <input> untuk membatasi jenis file yang dapat dipilih pengguna. Dalam contoh ini, pengguna hanya dapat memilih file dengan ekstensi .png, .jpg, atau .webp.

  • Keenam, atribut name="image" di tag <input> berfungsi menentukan nama parameter yang akan digunakan untuk mengakses data file di backend. Saat form dikirimkan, Laravel akan menangkap file ini melalui $request->file('image') yang ada di ImageController.php pada method store().

  • Ketujuh, adanya syntax blade @csrf yang digunakan untuk melindungi aplikasi dari serangan CSRF (Cross-Site Request Forgery). Token ini wajib disertakan dalam form yang menggunakan metode POST, PUT, atau DELETE. Laravel otomatis memverifikasi token ini untuk memastikan bahwa permintaan berasal dari aplikasi yang sah.

Langkah terakhir adalah membuat route agar aplikasi upload gambar di Laravel yang kita buat berjalan. Buka file web.php dan isi seperti kode di bawah:

<?php

use App\Http\Controllers\ImageController;
use Illuminate\Support\Facades\Route;

Route::controller(ImageController::class)
    ->group(function () {
        Route::get('', 'index')->name('home');
        Route::post('/images', 'store')->name('upload');
    });

Seiring berkembangnya aplikasi web, route juga akan semakin bertambah banyak. Jika tidak dikelola dengan benar, route yang menumpuk akan membuat sulit dalam pengembangan terutama saat melakukan debugging. Untuk mengatasi hal tersebut buatlah route yang bersih dan rapi, caranya bisa cek di artikel Tutorial Laravel: Mengelola Routing agar Rapi dan Mudah Dikembangkan.

5. Jalankan dan Uji Coba Fitur Upload Gambar

Sampai juga pada bagian akhir dari tutorial membuat fitur upload gambar di Laravel, pastikan tidak ada yang terlewat dan jangan lupa untuk disave. Kemudian jalankan:

php artisan serve

Silahkan coba untuk upload gambar, berikut adalah hasil milik saya:

Hasil dari Tutorial Membuat Fitur Upload File atau Gambar di Laravel dengan Storage

Agar tampilan upload gambar tidak monoton, kamu bisa menambahkan fitur preview gambar. Karena hal tersebut bisa meningkatan pengalaman pengguna, caranya bisa cek artikel Cara Membuat Fitur Preview Gambar Sebelum Upload.

Jika ingin mengetahui keseluruhan kode dari tutorial ini, teman-teman bisa mengunjungi GitHub Kode Fiksi.

Kesimpulan 

Artikel ini membahas langkah-langkah detail dalam membangun fitur upload gambar menggunakan framework Laravel. Dengan memanfaatkan fitur bawaan Laravel seperti File Storage dan validasi input, proses pengelolaan file menjadi lebih mudah, aman, dan terstruktur. Tutorial mencakup konfigurasi proyek Laravel, pembuatan controller, form upload dengan atribut yang relevan, hingga penggunaan symbolic link untuk mengakses file secara publik.

Menggunakan pendekatan ini, pengembang dapat menyimpan file dengan lebih terorganisir dan fleksibel, serta memiliki opsi untuk memperluas aplikasi dengan fitur tambahan, seperti preview gambar sebelum upload. Tutorial ini diharapkan dapat membantu pengembang Laravel dalam memahami dan mengimplementasikan fitur upload gambar pada proyek mereka dengan baik. Terima kasih sudah membaca hingga akhir!