Thứ Hai, 15 tháng 6, 2026

Upload File PHP – Lỗi "Không thấy file đâu" (Khi người dùng chọn file rất tự tin... nhưng server khẳng định chưa từng gặp nó)

Sáng Chủ Nhật đẹp trời, bạn hăng say đổ đầy nước vào hồ cá. Sau đó hớn hở đem cá tới để để đổ vào hồ thì "bàng hoàng" nhận ra hồ cá...không một giọt nước!


Giả sử bạn đang "vọc" PHP. Bạn làm chức năng upload ảnh.

Form rất đẹp.

Nút chọn file rất đẹp.


Người dùng chọn:

avatar.jpg


Bấm:

Upload


Bạn chờ đợi.


PHP trả về:

No file uploaded


Hoặc:

Undefined index: file


Hoặc tệ hơn:

Không báo lỗi gì

Nhưng file biến mất khỏi Trái Đất.



Upload file PHP không thấy file đâu là gì?


Đây là nhóm lỗi xảy ra khi:

  • Người dùng đã chọn file
  • Form đã submit
  • Nhưng PHP không nhận được file


Hoặc:

  • PHP nhận được file
  • Nhưng file không được lưu


Rất phổ biến với:

  • PHP thuần
  • Người mới học upload
  • InfinityFree
  • Shared Hosting


Ví dụ trớt quớt 

HTML:

<form method="post">

<input type="file" name="avatar">

<button>Upload</button>

</form>


PHP:

print_r($_FILES);


Kết quả:

Array

(

)


PHP:

"Tôi không thấy file nào."



Ví dụ thực tế

Bạn ra bưu điện gửi hàng.


Nhân viên hỏi:

"Kiện hàng của bạn đâu?"


Bạn trả lời:

"Tôi mang theo rồi."


Nhân viên:

"Không thấy."


Bạn nhìn xuống.

Thì ra quên mang kiện hàng từ xe vào.

Upload file lỗi thường cũng kiểu như vậy.


Quên enctype 


Đây là vua của mọi lỗi upload.


HTML sai:

<form method="post">

<input type="file" name="avatar">

</form>


Nhìn hoàn toàn bình thường.


Nhưng thiếu:


enctype="multipart/form-data"


Đúng phải là:

<form

method="post"

enctype="multipart/form-data">

<input type="file" name="avatar">

</form>


Nếu thiếu dòng này:

$_FILES

thường sẽ rỗng.



Đọc nhầm $_POST thay vì $_FILES 


Sai:

$file = $_POST['avatar'];


Đúng:

$file = $_FILES['avatar'];


Người mới rất hay nhầm chỗ này.


Sai tên field

HTML:

<input type="file" name="photo">


PHP:

$_FILES['avatar']


PHP:

photo ≠ avatar



Quên move_uploaded_file()

Nhiều bạn nghĩ:

$_FILES

xuất hiện là xong.


Không.


File đang nằm trong thư mục tạm.


Bạn phải:

move_uploaded_file(...)


Ví dụ:

move_uploaded_file(

    $_FILES['avatar']['tmp_name'],

    "uploads/avatar.jpg"

);


Nếu không:

File biến mất sau khi request kết thúc.


Ví dụ "trời ơi đất hỡi" 


Debug:

print_r($_FILES);

Thấy file.


Mở thư mục uploads:

Trống trơn


Nguyên nhân:

move_uploaded_file()

chưa chạy.


Thư mục uploads không tồn tại 

Code:

move_uploaded_file(

   $tmp,

   "uploads/avatar.jpg"

);


Nhưng thu mục:

uploads/

hoàn toàn không có.


Kết quả:

Upload thất bại. Thành công mới là lạ!


Quyền ghi thư mục (Permission)

Một số host:

Không cho ghi file


PHP nhận file.

Nhưng không lưu được.


Kết quả thì không nói ra ai cũng hiểu!



Tập tành làm web

Đây là lỗi khá phổ biến.


Localhost:

Upload được.


InfinityFree:

Không upload được.


Nguyên nhân thường là:

  • Sai đường dẫn
  • Sai thư mục
  • Thiếu thư mục uploads
  • File quá lớn

Không phải PHP ghét bạn.



File quá lớn 

Ví dụ:

video.mp4


Dung lượng:

500MB


Host cho:

10MB


Kết quả:


PHP có thể báo:

UPLOAD_ERR_INI_SIZE

Hoặc đơn giản là thất bại.


Quên kiểm tra lỗi upload

PHP có sẵn:

$_FILES['avatar']['error']


Ví dụ:

if($_FILES['avatar']['error'] != 0)

{

    echo "Upload lỗi";

}


Rất nhiều người bỏ qua bước này.


Sai đường dẫn 


Ví dụ:

uploads/avatar.jpg


Trong khi thực tế:

/public_html/uploads/


Kết quả:

File không lưu đúng nơi.



Code upload mẫu đúng 

HTML

<form

method="post"

enctype="multipart/form-data">



<input type="file" name="avatar">



<button>Upload</button>



</form>


PHP

<?php



if(isset($_FILES['avatar']))

{

    $tmp = $_FILES['avatar']['tmp_name'];



    $name = $_FILES['avatar']['name'];



    move_uploaded_file(

        $tmp,

        "uploads/" . $name

    );



    echo "Upload thành công ";

}

?>


Một sự thật thú vị 

Khoảng một nửa lỗi upload file của người mới là:

enctype="multipart/form-data"


Chỉ thiếu đúng một dòng.


Nhưng đủ để ngốn:

  • 2 giờ debug
  • 3 ly cà phê
  • 17 lần reload



Debug kiểu dev "xịn sò"

1. In toàn bộ $_FILES

print_r($_FILES);


Nếu rỗng:

Kiểm tra form.


2. Kiểm tra error

var_dump(

$_FILES['avatar']['error']

);


3. Kiểm tra thư mục uploads

Có tồn tại không?


4. Kiểm tra move_uploaded_file()

var_dump(

move_uploaded_file(...)

);


true hay false?


5. Test trên host thật

Đừng chỉ test localhost. Hoàn toàn có thể dùng những dịch vụ free hosting để làm việc đó.


Checklist chuẩn không cần chỉnh 

  • Có enctype="multipart/form-data"
  • Dùng $_FILES
  • Tên field đúng
  • Có move_uploaded_file()
  • Thư mục uploads tồn tại
  • Kiểm tra quyền ghi
  • Kiểm tra dung lượng file
  • Kiểm tra error
  • print_r($_FILES)


FAQ nhanh

Vì sao $_FILES rỗng?

Thường do thiếu:

multipart/form-data


Upload được trên localhost nhưng host fail?

Kiểm tra:

thư mục uploads

đường dẫn

dung lượng file


move_uploaded_file() có bắt buộc không?

Có.


Upload ảnh cần lưu database không?

Thường chỉ lưu:

Tên file

Đường dẫn file

Không lưu ảnh trực tiếp.


Bạn có thể cũng đang gặp 

👉 Form reload mất dữ liệu

👉 Checkbox trong PHP vì sao lúc có lúc không?

👉 PHP không nhận dữ liệu từ POST/GET

👉 Undefined Variable

👉 Redirect sau submit form đúng cách


Tổng kết

Upload file trong PHP nghe có vẻ đơn giản:

Chọn file

↓

Upload

↓

Xong

Nhưng thực tế có rất nhiều "cái bẫy":

  • thiếu enctype
  • sai $_FILES
  • quên move_uploaded_file()
  • thư mục không tồn tại
  • file quá lớn

Và hãy nhớ:

Nếu PHP nói "Tôi không thấy file đâu"...

Thì trước khi nghi ngờ server,

hãy kiểm tra xem bạn đã mang "kiện hàng" vào đúng cửa chưa.