Membuat Upload Multiple File dengan JavaScript dan PHP

Mengunggah banyak file sekaligus adalah fitur umum yang sangat berguna dalam banyak aplikasi web. Daripada harus memilih file satu per satu, pengguna bisa mengunggah semuanya sekaligus, menghemat waktu dan meningkatkan pengalaman. Tutorial ini akan memandu Anda membuat sistem upload multiple file menggunakan JavaScript (untuk bagian frontend) dan PHP (untuk bagian backend).

Kita akan membuat formulir sederhana di mana pengguna dapat memilih beberapa file. Dengan sedikit JavaScript, kita akan menangani proses pemilihan dan menampilkan pratinjau file sebelum diunggah. Di sisi PHP, kita akan memproses file-file tersebut, memvalidasinya, dan menyimpannya di server.

Struktur Project

Mari kita mulai dengan membuat struktur folder dasar untuk proyek kita:

multiple-upload/
├── index.html
├── upload.php
└── css/
    └── style.css

1. Frontend: HTML dan CSS

Buat file index.html

<!DOCTYPE html>
<html lang="id">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Multiple File Upload</title>
    <link rel="stylesheet" href="css/style.css">
</head>
<body>
    <div class="container">
        <h1>Upload Banyak File Sekaligus!</h1>
        <form id="uploadForm" enctype="multipart/form-data">
            <input type="file" id="fileInput" name="files[]" multiple accept="image/*, .pdf, .doc, .docx">
            <button type="submit" id="uploadButton">Unggah File</button>
        </form>

        <div id="fileList">
            <h2>File Terpilih:</h2>
            <ul id="selectedFiles">
                </ul>
        </div>

        <div id="uploadStatus"></div>
    </div>

    <script src="js/script.js"></script>
</body>
</html>

Buat file style.css dan masukkan ke dalam folder css

body {
    font-family: sans-serif;
    background-color: #f4f4f4;
    display: flex;
    justify-content: center;
    align-items: center;
    min-height: 100vh;
    margin: 0;
}

.container {
    background-color: #fff;
    padding: 30px;
    border-radius: 8px;
    box-shadow: 0 4px 8px rgba(0, 0, 0, 0.1);
    text-align: center;
    width: 90%;
    max-width: 600px;
}

h1 {
    color: #333;
    margin-bottom: 20px;
}

form {
    margin-bottom: 20px;
}

input[type="file"] {
    display: block;
    margin: 0 auto 15px auto;
    padding: 10px;
    border: 1px solid #ddd;
    border-radius: 4px;
    width: calc(100% - 22px);
}

button {
    background-color: #007bff;
    color: white;
    padding: 10px 20px;
    border: none;
    border-radius: 4px;
    cursor: pointer;
    font-size: 16px;
    transition: background-color 0.3s ease;
}

button:hover {
    background-color: #0056b3;
}

#fileList {
    text-align: left;
    margin-top: 20px;
    border-top: 1px solid #eee;
    padding-top: 20px;
}

#selectedFiles {
    list-style: none;
    padding: 0;
    margin: 0;
}

#selectedFiles li {
    background-color: #e9ecef;
    padding: 8px 12px;
    margin-bottom: 5px;
    border-radius: 4px;
    display: flex;
    justify-content: space-between;
    align-items: center;
    font-size: 0.9em;
}

#selectedFiles li span {
    font-weight: bold;
}

#uploadStatus {
    margin-top: 20px;
    padding: 10px;
    border-radius: 4px;
    font-weight: bold;
}

.success {
    background-color: #d4edda;
    color: #155724;
}

.error {
    background-color: #f8d7da;
    color: #721c24;
}

2. Frontend: JavaScript

Buat file script.js dan masukkan ke dalam folder js

document.addEventListener('DOMContentLoaded', () => {
    const fileInput = document.getElementById('fileInput');
    const uploadForm = document.getElementById('uploadForm');
    const selectedFilesList = document.getElementById('selectedFiles');
    const uploadStatus = document.getElementById('uploadStatus');

    // Menampilkan daftar file yang dipilih
    fileInput.addEventListener('change', () => {
        selectedFilesList.innerHTML = ''; // Bersihkan daftar sebelumnya
        uploadStatus.innerHTML = ''; // Bersihkan status

        const files = fileInput.files;
        if (files.length === 0) {
            selectedFilesList.innerHTML = '<li>Tidak ada file terpilih.</li>';
            return;
        }

        for (let i = 0; i < files.length; i++) {
            const file = files[i];
            const listItem = document.createElement('li');
            listItem.innerHTML = `<span>${file.name}</span> (${(file.size / 1024).toFixed(2)} KB)`;
            selectedFilesList.appendChild(listItem);
        }
    });

    // Mengirim formulir via AJAX
    uploadForm.addEventListener('submit', async (e) => {
        e.preventDefault(); // Mencegah pengiriman formulir default

        const formData = new FormData();
        const files = fileInput.files;

        if (files.length === 0) {
            uploadStatus.className = 'error';
            uploadStatus.textContent = 'Pilih setidaknya satu file untuk diunggah!';
            return;
        }

        // Tambahkan setiap file ke FormData
        for (let i = 0; i < files.length; i++) {
            formData.append('files[]', files[i]);
        }

        uploadStatus.className = '';
        uploadStatus.textContent = 'Mengunggah...';

        try {
            const response = await fetch('upload.php', {
                method: 'POST',
                body: formData,
            });

            const result = await response.json(); // Mengasumsikan respons adalah JSON

            if (result.status === 'success') {
                uploadStatus.className = 'success';
                uploadStatus.textContent = result.message;
                // Opsional: Bersihkan daftar file setelah berhasil upload
                selectedFilesList.innerHTML = '';
                fileInput.value = ''; // Reset input file
            } else {
                uploadStatus.className = 'error';
                uploadStatus.textContent = result.message || 'Terjadi kesalahan saat mengunggah.';
            }
        } catch (error) {
            console.error('Error:', error);
            uploadStatus.className = 'error';
            uploadStatus.textContent = 'Terjadi kesalahan jaringan atau server.';
        }
    });
});

3. Backend: PHP

Sekarang, kita akan membuat upload.php yang akan memproses file yang dikirim dari frontend. Pastikan Anda memiliki folder uploads/ di direktori yang sama dengan upload.php. Folder ini akan menjadi tempat file disimpan.

<?php
header('Content-Type: application/json'); // Beri tahu browser bahwa respons adalah JSON

$uploadDirectory = 'uploads/'; // Direktori tempat file akan disimpan

// Buat direktori jika belum ada
if (!is_dir($uploadDirectory)) {
    mkdir($uploadDirectory, 0777, true);
}

if (isset($_FILES['files']) && is_array($_FILES['files'])) {
    $uploadedFiles = $_FILES['files'];
    $totalFiles = count($uploadedFiles['name']);
    $errors = [];
    $uploadedCount = 0;

    for ($i = 0; $i < $totalFiles; $i++) {
        $fileName = $uploadedFiles['name'][$i];
        $fileTmpName = $uploadedFiles['tmp_name'][$i];
        $fileSize = $uploadedFiles['size'][$i];
        $fileError = $uploadedFiles['error'][$i];
        $fileType = $uploadedFiles['type'][$i];

        $fileExt = strtolower(pathinfo($fileName, PATHINFO_EXTENSION));
        $allowed = ['jpg', 'jpeg', 'png', 'gif', 'pdf', 'doc', 'docx']; // Jenis file yang diizinkan

        if ($fileError === UPLOAD_ERR_OK) {
            // Validasi jenis file
            if (in_array($fileExt, $allowed)) {
                // Validasi ukuran file (misalnya, maks 5MB)
                if ($fileSize < 5000000) { // 5MB
                    $fileDestination = $uploadDirectory . $fileName;

                    if (move_uploaded_file($fileTmpName, $fileDestination)) {
                        $uploadedCount++;
                    } else {
                        $errors[] = "Gagal memindahkan file '$fileName'.";
                    }
                } else {
                    $errors[] = "Ukuran file '$fileName' terlalu besar (maks 5MB).";
                }
            } else {
                $errors[] = "Jenis file '$fileName' tidak diizinkan.";
            }
        } else {
            $errors[] = "Terjadi kesalahan saat mengunggah '$fileName' (Kode error: $fileError).";
        }
    }

    if ($uploadedCount > 0 && empty($errors)) {
        echo json_encode([
            'status' => 'success',
            'message' => "$uploadedCount file berhasil diunggah!",
        ]);
    } elseif ($uploadedCount > 0 && !empty($errors)) {
        echo json_encode([
            'status' => 'warning',
            'message' => "$uploadedCount file berhasil diunggah, tetapi ada kesalahan: " . implode(', ', $errors),
        ]);
    } else {
        echo json_encode([
            'status' => 'error',
            'message' => "Gagal mengunggah semua file. " . implode(', ', $errors),
        ]);
    }
} else {
    echo json_encode([
        'status' => 'error',
        'message' => 'Tidak ada file yang diterima.',
    ]);
}
?>

Sekarang silahkan uji coba source code tersebut.




Posting Komentar

0 Komentar