Membuat Sistem Pengarsipan Dokumen Simpel: Upload File di Laravel Cuma 3 Langkah

Membangun sistem pengarsipan dokumen sebenarnya tidak sesulit yang dibayangkan, terutama ketika menggunakan Laravel yang sudah menyediakan banyak fitur bawaan untuk mempermudah prosesnya.

Dengan pendekatan yang tepat, kamu bisa membuat sebuah sistem upload, simpan, dan kelola file yang rapi, aman, serta mudah diakses hanya dalam hitungan menit. Pada panduan ini, kita akan membangun flow pengarsipan yang benar-benar sederhana namun tetap mengikuti standar profesional, sehingga cocok untuk digunakan di proyek internal, aplikasi kantor, maupun kebutuhan pribadi.

Lebih kerennya lagi, seluruh proses ini hanya memerlukan tiga langkah inti, mulai dari menyiapkan project, membuat form dan route untuk upload file, hingga menangani proses penyimpanan dokumen ke storage.

Setiap langkah sudah dirancang agar mengalir dan mudah dipahami, sehingga kamu bisa mengikuti tanpa kebingungan baik kamu masih pemula maupun sudah terbiasa menggunakan Laravel. Setelah semua selesai, kamu punya sistem pengarsipan dokumen yang siap dikembangkan lagi menjadi lebih lengkap sesuai kebutuhan.

1. Setup & Persiapan Project

Dengan penuh semangat kita mulai dari fondasi paling penting: memastikan project Laravel kamu siap berjalan dengan stabil dan rapi! Pada tahap Setup & Persiapan Project ini, kamu hanya perlu membuat atau membuka project Laravel yang sudah ada, mengatur koneksi database di file .env, dan menjalankan perintah php artisan storage:link agar seluruh file yang di-upload nantinya dapat diakses dengan aman melalui folder storage.

Langkah ini sederhana tetapi sangat menentukan, karena memastikan lingkungan kerjamu sudah tertata, tersambung ke database, dan siap untuk proses upload dokumen yang akan kita bangun pada langkah berikutnya! πŸš€

1.1. Buat Project Laravel (opsional jika sudah punya)

laravel new arsip-dokumen

Perintah laravel new arsip-dokumen digunakan untuk membuat sebuah project Laravel baru dengan nama arsip-dokumen, sehingga kamu langsung mendapatkan struktur aplikasi lengkap yang siap kita kembangkan di selanjutnya.

Pastikan database kalian/ phpmyadmin kalian sudah berjalan.

Hasil

Nanti akan di tanyakan sebagai berikut maka kalian pilih ini:

# Which database will your application use? [SQLite]: Pilih MySQL

# Default database updated. Would you like to run the default database migrations? (yes/no) [yes]: Pilih Yes

cd arsip-dokumen

code .

Hasil

1.2. Atur koneksi database di .env

Selanjutnya masuk ke .env dan perhatikan pada kode ini yaitu berikut yang perlu di ubah:

DB_CONNECTION=mysql
DB_HOST=127.0.0.1
DB_PORT=3306
DB_DATABASE=arsip_docs
DB_USERNAME=root
DB_PASSWORD=

Baris konfigurasi tersebut digunakan untuk menghubungkan project Laravel ke database MySQL lokal dengan nama database arsip_docs menggunakan username root dan port 3306, sehingga aplikasi bisa menyimpan dan membaca data dengan benar.

Hasil

1.3. Jalankan storage link

Supaya file bisa diakses publik jalan ini di terminal proyek kamu:

php artisan storage:link

Perintah php artisan storage:link berfungsi membuat tautan simbolis antara folder storage dan public, sehingga file yang kamu upload dapat diakses secara aman dan terlihat oleh pengguna melalui URL publik.

Hasil

2. Buat Form Upload + Route

Setelah project kamu siap dan lingkungan kerjanya sudah tertata dengan benar, sekarang kita masuk ke bagian yang mulai terasa seru: membuat form upload dan route sebagai pintu utama bagi pengguna untuk mengirimkan dokumen ke sistem.

Pada tahap ini, kita akan menyiapkan tampilan sederhana menggunakan Blade untuk menampung input file, sekaligus mendefinisikan route yang akan menangani proses pengiriman data tersebut ke controller.

Bagian ini adalah fondasi dari seluruh alur pengarsipan, karena di sinilah pengguna pertama kali berinteraksi dengan aplikasi dan sistem menerima file yang akan disimpan.

2.1. Buat Migration Untuk Menyimpan Data File

Ketikkan ini di terminal proyek kamu:

php artisan make:migration create_documents_table

Perintah php artisan make:migration create_documents_table digunakan untuk membuat file migration baru yang nanti akan membentuk struktur tabel documents di database agar data file yang di-upload dapat disimpan dengan rapi.

Hasil

Lalu masuk ke filenya dan edit filenya:

public function up()
{
    Schema::create('documents', function (Blueprint $table) {
        $table->id();
        $table->string('filename');
        $table->string('path');
        $table->timestamps();
    });
}

Kode up() tersebut berfungsi membuat tabel documents di database dengan kolom seperti id, filename, path, dan timestamps, sehingga setiap file yang di-upload dapat dicatat dan dikelola dengan struktur data yang jelas.

Lalu jalankan migration:

php artisan migrate

Perintah php artisan migrate digunakan untuk mengeksekusi seluruh file migration yang ada sehingga struktur tabel yang telah didefinisikan langsung dibuat di dalam database.

Hasil

2.2. Buat Route Upload

Dilanjutkan dengan tambahkan di routes/web.php:

use App\\Http\\Controllers\\DocumentController;

Route::get('/', [DocumentController::class, 'index'])->name('documents.index');
Route::post('/upload', [DocumentController::class, 'store'])->name('documents.store');

Kode tersebut memanggil DocumentController dan mendefinisikan dua route, yaitu route GET untuk menampilkan daftar dokumen serta route POST untuk memproses upload file, sehingga alur pengarsipan dapat berjalan dari tampilan pengguna hingga penyimpanan data.

Hasil

2.3. Buat Form Upload (Blade)

Lalu di lanjut Buat file: resources/views/documents.blade.php dan isi:

<!DOCTYPE html>
<html>
<head>
    <title>Arsip Dokumen</title>
</head>
<body>

    <h2>Upload Dokumen</h2>

    <form action="{{ route('documents.store') }}" method="POST" enctype="multipart/form-data">
        @csrf
        <input type="file" name="file" required>
        <button type="submit">Upload</button>
    </form>

    <h3>Daftar Dokumen</h3>
    <ul>
        @foreach ($documents as $doc)
            <li>
                <a href="{{ asset('storage/' . $doc->path) }}" target="_blank">
                    {{ $doc->filename }}
                </a>
            </li>
        @endforeach
    </ul>

</body>
</html>

Hasil

3. Proses Upload + Simpan ke Storage

Setelah form upload dan route berhasil dibuat, kini kita masuk ke inti utama dari sistem pengarsipan dokumen, yaitu proses menangani file yang dikirim pengguna dan menyimpannya secara aman di dalam storage.

Pada tahap ini, kita akan membuat controller yang bertugas memvalidasi file, menyimpannya ke folder yang tepat, serta mencatat informasi dokumen tersebut ke database agar bisa ditampilkan kembali.

Inilah bagian yang memastikan setiap dokumen tidak hanya diterima, tetapi juga tersimpan dengan rapi, terstruktur, dan mudah diakses kapan pun dibutuhkan.

3.1. Buat Controller

Ketikkan di terminal:

php artisan make:controller DocumentController

Perintah php artisan make:controller DocumentController digunakan untuk membuat sebuah controller baru bernama DocumentController, yang nantinya akan menangani logika upload, penyimpanan, dan pengelolaan dokumen.

3.2. Isi logika controller

Lalu isi kode berikut di dalam app/Http/Controllers/DocumentController.php:

namespace App\\Http\\Controllers;

use Illuminate\\Http\\Request;
use App\\Models\\Document;

class DocumentController extends Controller
{
    public function index()
    {
        $documents = Document::latest()->get();
        return view('documents', compact('documents'));
    }

    public function store(Request $request)
    {
        // Validasi
        $request->validate([
            'file' => 'required|file|max:2048',
        ]);

        // Simpan file ke storage/app/public/documents
        $path = $request->file('file')->store('documents', 'public');

        // Simpan data ke database
        Document::create([
            'filename' => $request->file('file')->getClientOriginalName(),
            'path'     => $path,
        ]);

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

3.3. Model Document

Selanjutnya jalankan perintah ini di terminal:

php artisan make:model Document

Perintah php artisan make:model Document digunakan untuk membuat model Document yang akan merepresentasikan data dokumen di dalam database, sehingga setiap file yang disimpan dapat diakses dan dikelola melalui Eloquent.

Hasil

Masuk ke dalam filenya lalu Isi minimal:

namespace App\\Models;

use Illuminate\\Database\\Eloquent\\Model;

class Document extends Model
{
    protected $fillable = ['filename', 'path'];
}

Kode model tersebut mendefinisikan kelas Document yang mewakili tabel dokumen di database dan menentukan bahwa kolom filename dan path boleh diisi secara massal, sehingga penyimpanan data file menjadi lebih mudah dan aman.

Hasil

4. Tampilkan, Download, atau Hapus Dokumen

Setelah proses upload dan penyimpanan dokumen berhasil berjalan dengan baik, langkah berikutnya adalah memberikan fitur lanjutan agar pengguna dapat berinteraksi lebih jauh dengan file yang telah diarsipkan.

Pada tahap ini, kita akan menambahkan kemampuan untuk menampilkan daftar dokumen secara rapi, menyediakan tombol download agar file bisa diunduh kembali kapan pun dibutuhkan, serta memberikan opsi hapus untuk mengelola dokumen yang sudah tidak relevan.

Fitur-fitur ini membuat sistem pengarsipan terasa jauh lebih lengkap dan fungsional, karena pengguna tidak hanya mengunggah dokumen, tetapi juga dapat mengatur, mengambil, dan membersihkannya dengan mudah.

4.1. Tambah Route Download & Delete

Masuk dan beri kode berikut di web.php:

Route::get('/download/{id}', [DocumentController::class, 'download'])->name('documents.download');
Route::delete('/delete/{id}', [DocumentController::class, 'destroy'])->name('documents.delete');

Kode tersebut mendefinisikan dua route yang masing-masing digunakan untuk mengunduh dokumen berdasarkan ID dan menghapus dokumen dari sistem, sehingga pengguna dapat mengelola file yang sudah diarsipkan dengan lebih lengkap dan fleksibel.

Hasil

4.2. Tambah fungsi download + delete pada controller

Lalu tambahkan kode berikut di dalam app/Http/Controllers/DocumentController.php:

use Illuminate\\Support\\Facades\\Storage;

public function download($id)
{
    $doc = Document::findOrFail($id);
    return Storage::disk('public')->download($doc->path, $doc->filename);
}

public function destroy($id)
{
    $doc = Document::findOrFail($id);

    // Hapus file fisik
    Storage::disk('public')->delete($doc->path);

    // Hapus database
    $doc->delete();

    return redirect()->back()->with('success', 'Dokumen berhasil dihapus!');
}

Hasil

4.3. Update Blade: Tambah tombol download & delete

Lalu di lanjut edit kode ini di file: resources/views/documents.blade.php yaitu:

@foreach ($documents as $doc)
    <li>
        <a href="{{ asset('storage/' . $doc->path) }}" target="_blank">
            {{ $doc->filename }}
        </a>

        | <a href="{{ route('documents.download', $doc->id) }}">Download</a>

        <form action="{{ route('documents.delete', $doc->id) }}" method="POST" style="display:inline;">
            @csrf
            @method('DELETE')
            <button type="submit">Hapus</button>
        </form>
    </li>
@endforeach

Hasil

4.4. Memberi Tailwind CSS Agar Tampil Menarik

Sekarang biar lebih cantik kita beri Tailwind CSS yaitu dengan cara masukkan ini ke dalam views/documents.blade.php

<!DOCTYPE html>
<html>
<head>
    <title>Arsip Dokumen</title>
    <script src="<https://cdn.tailwindcss.com>"></script>
</head>
<body>
    <div class="flex w-full">

    <div class="sidebar min-h-screen w-64 bg-white border-r border-gray-200 p-4 shadow-lg">
            <div class="text-xl font-bold mb-8">LOGO</div>
            <nav>
                <ul>
                    <li class="mb-2">
                        <a href="#" class="flex items-center p-2 text-gray-700 hover:bg-gray-100 rounded-lg font-semibold bg-gray-100 border-l-4 border-blue-600">
                            <svg class="w-5 h-5 mr-3" fill="none" stroke="currentColor" viewBox="0 0 24 24" xmlns="<http://www.w3.org/2000/svg>"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M3 10h18M3 14h18m-9-4v8m-7 0h14a2 2 0 002-2V8a2 2 0 00-2-2H5a2 2 0 00-2 2v8a2 2 0 002 2z"></path></svg>
                            Merino
                        </a>
                    </li>
                    <li class="mb-2">
                        <a href="#" class="flex items-center p-2 text-gray-500 hover:bg-gray-100 rounded-lg">
                            <svg class="w-5 h-5 mr-3" fill="none" stroke="currentColor" viewBox="0 0 24 24" xmlns="<http://www.w3.org/2000/svg>"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M4 16v1a3 3 0 003 3h10a3 3 0 003-3v-1m-4-4l-4 4m0 0l-4-4m4 4V4"></path></svg>
                            Desse Filent
                        </a>
                    </li>
                    <li class="mb-2">
                        <a href="#" class="flex items-center p-2 text-gray-500 hover:bg-gray-100 rounded-lg">
                            <svg class="w-5 h-5 mr-3" fill="none" stroke="currentColor" viewBox="0 0 24 24" xmlns="<http://www.w3.org/2000/svg>"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M19 11H5m14 0a2 2 0 012 2v6a2 2 0 01-2 2H5a2 2 0 01-2-2v-6a2 2 0 012-2m14 0V9a2 2 0 00-2-2M5 11V9a2 2 0 012-2m0 0V5a2 2 0 012-2h6a2 2 0 012 2v2M7 7h10"></path></svg>
                            Somgrodion
                        </a>
                    </li>
                    <li class="mb-2">
                        <a href="#" class="flex items-center p-2 text-gray-500 hover:bg-gray-100 rounded-lg">
                            <svg class="w-5 h-5 mr-3" fill="none" stroke="currentColor" viewBox="0 0 24 24" xmlns="<http://www.w3.org/2000/svg>"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M8 14v3m4-3v3m4-3v3M3 21h18M3 10h18M3 7l9-4 9 4M4 10h16v11H4V10z"></path></svg>
                            Fripus
                        </a>
                    </li>
                </ul>
            </nav>
            
            <div class="mt-8 pt-4 border-t border-gray-200">
                <a href="#" class="flex items-center p-2 text-red-500 hover:bg-red-50 rounded-lg">
                    <!-- Logout (outline) -->
                    <svg width="24" height="24" viewBox="0 0 24 24" fill="none"
                        xmlns="<http://www.w3.org/2000/svg>" aria-hidden="true">
                    <!-- Door / panel -->
                    <rect x="3" y="3" width="10" height="18" rx="2" stroke="#f14141ff" stroke-width="2"/>
                    <!-- Arrow pointing out -->
                    <path d="M14 12h6" stroke="#f14141ff" stroke-width="2" stroke-linecap="round"/>
                    <path d="M17 9l3 3-3 3" fill="none" stroke="#f14141ff" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
                    </svg>

                    Logout
                </a>
            </div>
        </div>

        <div class="flex-1 flex flex-col gap-7 p-4">

            <div class="flex flex-col gap-4">
            <h2 class="text-gray-800 font-semibold text-xl">Upload Dokumen</h2>

            <form action="{{ route('documents.store') }}" method="POST" enctype="multipart/form-data">
                @csrf
                <input type="file" name="file" required>
                <button type="submit" class="bg-blue-600 hover:bg-blue-700 text-white font-semibold py-2 px-4 rounded-lg shadow-md transition duration-300 ease-in-out">Upload</button>
            </form>
            </div>

            <div class="flex flex-col gap-4">
            <h3 class="text-gray-800 font-semibold text-xl">Daftar Dokumen</h3>
            <table class="min-w-full border border-gray-300 rounded-lg overflow-hidden">
                <thead class="bg-gray-100">
                    <tr>
                        <th class="px-4 py-2 border-b text-left">Nama Dokumen</th>
                        <th class="px-4 py-2 border-b text-left">Aksi</th>
                    </tr>
                </thead>

                <tbody>
                    @foreach ($documents as $doc)
                        <tr class="hover:bg-gray-50 transition">
                            <!-- Nama File -->
                            <td class="px-4 py-2 border-b">
                                <a href="{{ asset('storage/' . $doc->path) }}" 
                                target="_blank" 
                                class="text-black hover:font-medium hover:text-blue-600 transitions-all duration-300">
                                    {{ $doc->filename }}
                                </a>
                            </td>

                            <!-- Tombol Aksi -->
                            <td class="px-4 py-2 border-b flex gap-2">

                                <!-- Download -->
                                <a href="{{ route('documents.download', $doc->id) }}"
                                class="bg-green-600 hover:bg-green-700 text-white font-semibold py-2 px-4 rounded-lg shadow transition">
                                Download
                                </a>

                                <!-- Hapus -->
                                <form action="{{ route('documents.delete', $doc->id) }}" 
                                    method="POST" 
                                    onsubmit="return confirm('Yakin mau hapus dokumen ini?')">
                                    @csrf
                                    @method('DELETE')
                                    <button type="submit" 
                                            class="bg-red-600 hover:bg-red-700 text-white font-semibold py-2 px-4 rounded-lg shadow transition">
                                        Hapus
                                    </button>
                                </form>

                            </td>
                        </tr>
                    @endforeach
                </tbody>
            </table>

            </div>

        </div>

    </div>
</body>
</html>

Hasil

Jalankan

php artisan serve
# klik Server running on [<http://127.0.0.1:8000>].

Hasil

4.5. Demo Rangkuman Hasil Proyek

Berikut hasil dari seluruh kode yang telah kita buat:

πŸŽ‰ 5. Selesai!

Kamu sekarang sudah banyak belajar dan praktek yaitu:

βœ” Upload dokumen

βœ” Simpan ke storage

βœ” Catat ke database

βœ” List dokumen

βœ” Download

βœ” Delete

βœ” Styling Tailwind CSS

Ini adalah kerangka terbaik dalam SISTEM ARSIP DOKUMEN LENGKAP!

🏒 6. Rekomendasi Kelas BuildWithAngga

Jika kamu sudah berhasil membangun sistem pengarsipan dokumen sederhana ini, selamat! πŸŽ‰ Kamu baru saja menguasai salah satu fondasi penting yang digunakan di berbagai aplikasi profesional, mulai dari HR system, warehouse management, hingga platform e-commerce. Namun, perjalananmu dalam mengembangkan aplikasi Laravel tidak harus berhenti di sini.

Untuk kamu yang ingin naik level lebih cepat, memahami alur bisnis nyata, serta belajar membuat aplikasi yang benar-benar dipakai di dunia kerja, ada satu rekomendasi belajar yang bener-bener wajib kamu ikuti, terutama jika kamu ingin masuk ke level developer siap kerja:

7. Rekomendasi Kelas Terbaik & Terbaru (Wajib Ikut!)

πŸš€ 7.1. Kelas Ebook Laravel 12: Bikin Web Manajemen Gudang dan Point of Sale

Berikut Linknya: https://buildwithangga.com/kelas/ebook-laravel-12-bikin-web-manajemen-gudang-dan-point-of-sale?main_leads=searchsuggestion

πŸ”₯ Kelas terbaru, paling up-to-date, dan dirancang khusus berdasarkan kebutuhan industri saat ini!

Di kelas ini, kamu tidak hanya belajar teori, tetapi benar-benar dibimbing membuat aplikasi lengkap yang dipakai di banyak bisnis modern. Kelas ini adalah paket komplit untuk membangun pondasi Laravel kamu ke level profesional, karena di dalamnya kamu akan belajar:

βœ… 7.1.1. Membangun Sistem Manajemen Gudang dari Nol

Mulai dari struktur database, pencatatan barang, mutasi stok, hingga laporan yang bisa dipahami tim operasional.

βœ… 7.1.2. Membuat Sistem Point of Sale (POS) Modern

Lengkap dengan:

  • transaksi real-time
  • pengurangan stok otomatis
  • hingga invoice siap cetak

persis seperti aplikasi yang dipakai minimarket dan retail.

βœ… 7.1.3. Workflow Bisnis Industri Nyata

Kamu bakal paham cara kerja gudang dan toko modern yang itu sesuatu yang jarang diajarkan di kelas lain.

βœ… 7.1.4. Laravel 12 (Versi Terbaru)

Kamu belajar langsung menggunakan fitur terbaru Laravel biar langsung siap kerja.

βœ… 7.1.5. Studi Kasus Lengkap & Aplikatif

Bukan teori, tapi benar-benar membangun aplikasi yang bisa kamu pakai dan jadikan portofolio premium.

βœ… 7.1.6. Cocok untuk Developer Pemula hingga Menengah

Materi dirangkai bertahap, jelas, dan mudah diterapkan.

🎯 8. Kesimpulan

Kalau kamu sudah merasa nyaman dengan upload file, pengarsipan dokumen, dan CRUD dasar, ini saatnya naik kelas ke proyek yang lebih kompleks dan lebih β€œbernilai industri”.

Kelas Ebook Laravel 12 Bikin Web Manajemen Gudang dan Point of Sale adalah langkah paling tepat, apalagi jika kamu ingin:

  • meningkatkan skill Laravel dengan cepat
  • membangun portofolio profesional
  • memahami alur bisnis nyata
  • siap masuk dunia kerja atau freelancer

Berikut Linknya: https://buildwithangga.com/kelas/ebook-laravel-12-bikin-web-manajemen-gudang-dan-point-of-sale?main_leads=searchsuggestion

Jangan tunda upgrade skill kamu karena dunia teknologi bergerak cepat, dan kelas ini adalah jalan pintas paling efektif untuk mengejar peluang besar di industri!

Siap level-up? πŸš€πŸ”₯