Upload File PHP Gagal? 7 Penyebab yang Paling Sering

Upload file di PHP terlihat sederhana, tetapi titik gagalnya banyak. Dari sisi user, gejalanya biasanya cuma satu: klik tombol upload, lalu file tidak muncul, preview kosong, atau aplikasi menampilkan pesan gagal.

Masalah upload hampir selalu bisa dilacak kalau kamu memeriksa tiga hal sekaligus: isi $_FILES, konfigurasi server, dan folder tujuan di project.

Kapan Error Ini Biasanya Muncul?

  • File terasa "tidak terkirim" setelah form submit
  • move_uploaded_file() selalu mengembalikan false
  • Upload aman di lokal, tetapi gagal di server production
  • File besar gagal, tetapi file kecil berhasil
  • Hanya tipe file tertentu yang selalu ditolak

7 Penyebab yang Paling Sering

1. Form Tidak Memakai enctype="multipart/form-data"

<form action="upload.php" method="POST">
    <input type="file" name="foto">
</form>

Tanpa enctype, browser tidak akan mengirim file dengan benar.

2. Nama Input Tidak Cocok

Kalau HTML memakai name="gambar", tetapi PHP membaca $_FILES['foto'], hasilnya akan terlihat seperti file tidak pernah dikirim.

3. Folder Tujuan Belum Ada atau Tidak Bisa Ditulis

move_uploaded_file() tidak akan sukses kalau folder target seperti uploads/ tidak tersedia atau permission-nya salah.

4. Ukuran File Melebihi Batas PHP

Konfigurasi yang paling sering membatasi upload:

  • upload_max_filesize
  • post_max_size
  • max_file_uploads

Kalau file melebihi batas ini, PHP akan memberi kode error upload.

5. File Gagal di Folder Sementara

Sebelum dipindahkan, file lebih dulu disimpan di folder temporary server. Kalau folder temp bermasalah, tmp_name bisa kosong atau tidak valid.

6. Validasi Ekstensi atau MIME Type Terlalu Ketat

Kadang file sebenarnya valid, tetapi logic aplikasi menolak karena hanya mengecek ekstensi, bukan MIME type, atau sebaliknya.

7. Path Tujuan Salah

<?php
$tujuan = "upload/" . $namaFile;
move_uploaded_file($tmpName, $tujuan);

Kalau folder yang benar ternyata uploads/, file pasti gagal dipindahkan.

Langkah Diagnosis

1. Lihat Isi $_FILES

<?php
echo '<pre>';
print_r($_FILES);
echo '</pre>';

Pastikan key seperti name, tmp_name, size, dan error benar-benar ada.

2. Cek Kode Error Upload

<?php
$error = $_FILES['foto']['error'] ?? null;
var_dump($error);

Kode 0 berarti upload sampai ke server. Kalau bukan 0, fokus dulu ke penyebab upload-nya, bukan ke move_uploaded_file().

3. Cek Folder Tujuan

<?php
var_dump(is_dir(__DIR__ . '/uploads'));
var_dump(is_writable(__DIR__ . '/uploads'));

4. Cek Ukuran Maksimal PHP

<?php
echo ini_get('upload_max_filesize');
echo ini_get('post_max_size');

5. Cek Path Tujuan yang Dipakai

Kadang bug-nya sesederhana relative path yang tidak mengarah ke folder yang kamu kira.

Mulai dari

error dan tmp_name Kalau $_FILES['foto']['error'] bukan 0 atau tmp_name kosong, masalahnya terjadi sebelum file sempat dipindahkan ke folder tujuan.

Langkah Fix

1. Perbaiki Form HTML

<form action="upload.php" method="POST" enctype="multipart/form-data">
    <input type="file" name="foto" required>
    <button type="submit">Upload</button>
</form>

2. Validasi Error Upload Lebih Dulu

<?php
$file = $_FILES['foto'] ?? null;

if (!$file || $file['error'] !== UPLOAD_ERR_OK) {
    exit('Upload gagal sebelum file diproses.');
}

3. Gunakan Path Absolut yang Jelas

<?php
$folder = __DIR__ . '/uploads';
$tujuan = $folder . '/' . basename($file['name']);

4. Pastikan Folder Ada

<?php
if (!is_dir($folder)) {
    mkdir($folder, 0755, true);
}

5. Batasi Ukuran dan Tipe File

<?php
$allowed = ['jpg', 'jpeg', 'png'];
$ext = strtolower(pathinfo($file['name'], PATHINFO_EXTENSION));

if (!in_array($ext, $allowed, true)) {
    exit('Tipe file tidak diizinkan.');
}

if ($file['size'] > 2 * 1024 * 1024) {
    exit('Ukuran file maksimal 2 MB.');
}

Contoh Sebelum dan Sesudah

Sebelum

<?php
$tmpName = $_FILES['foto']['tmp_name'];
move_uploaded_file($tmpName, 'uploads/' . $_FILES['foto']['name']);

Kode ini terlalu optimistis karena belum mengecek apakah file benar-benar terkirim, folder tersedia, dan error upload bernilai 0.

Sesudah

<?php
$file = $_FILES['foto'] ?? null;
$folder = __DIR__ . '/uploads';

if (!$file || $file['error'] !== UPLOAD_ERR_OK) {
    exit('Upload gagal.');
}

if (!is_dir($folder)) {
    mkdir($folder, 0755, true);
}

$namaAman = uniqid('foto-', true) . '.' . strtolower(pathinfo($file['name'], PATHINFO_EXTENSION));
$tujuan = $folder . '/' . $namaAman;

if (!move_uploaded_file($file['tmp_name'], $tujuan)) {
    exit('File gagal dipindahkan.');
}

Error Umum

UPLOAD_ERR_INI_SIZE

File melebihi batas upload_max_filesize di konfigurasi PHP.

UPLOAD_ERR_NO_FILE

Browser tidak mengirim file sama sekali. Biasanya input file kosong atau nama key tidak sesuai.

move_uploaded_file(): Failed to open stream

Biasanya path tujuan salah atau folder target tidak bisa ditulis.

File Besar Selalu Gagal

Periksa post_max_size, bukan hanya upload_max_filesize.

Pencegahan

  1. Selalu cek $_FILES['...']['error'] sebelum memproses file.
  2. Gunakan enctype="multipart/form-data" di form upload.
  3. Pakai nama file baru yang aman, jangan simpan nama asli mentah.
  4. Simpan file di folder yang memang dikhususkan untuk upload.
  5. Dokumentasikan batas ukuran dan tipe file di UI agar user tahu ekspektasinya.

Bacaan Terkait

FAQ

Kenapa file kecil bisa di-upload, tetapi file besar gagal?

Biasanya karena batas upload_max_filesize atau post_max_size di PHP terlalu kecil.

Apakah cukup memeriksa ekstensi file?

Tidak. Untuk keamanan yang lebih baik, cek juga MIME type dan jangan izinkan file executable di-upload ke folder publik sembarangan.

Kenapa upload aman di lokal tetapi gagal di hosting?

Sering disebabkan oleh permission folder, batas ukuran server, atau konfigurasi temporary upload directory yang berbeda.