Tại sao $ _FILES trống khi tải tệp lên PHP?


145

Tôi đã cài đặt WampServer 2 trên máy tính Windows 7 của mình. Tôi đang sử dụng Apache 2.2.11 và PHP 5.2.11. Khi tôi cố tải lên bất kỳ tệp nào từ một biểu mẫu, nó dường như tải lên, nhưng trong PHP, $_FILESmảng trống. Không có tập tin trong c:\wamp\tmpthư mục. Tôi đã cấu hình php.iniđể cho phép tải lên tập tin và như vậy. Các tmpthư mục đã đọc đặc quyền / ghi cho người dùng hiện. Tôi bối rối.

HTML:

<html>
<head>
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
</head>
<body>
    <form enctype="multipart/form-data" action="vanilla-upload.php" method="POST">
        Choose a file to upload: <input name="uploadedfile" type="file" /><br />
        <input type="submit" value="Upload File" />
    </form>
</body>
</html>

PHP:

<?php
echo 'file count=', count($_FILES),"\n";
var_dump($_FILES);
echo "\n";
?>

2
Bạn đã kiểm tra các bản ghi lỗi?
Byron Whitlock

Tôi chắc chắn có một cái gì đó ngớ ngẩn mà bạn đang nhìn. Ví dụ, bạn có chắc chắn có mã trong vanilla-upload.php?
Luca Matteis

Hà tôi đã có cùng một vấn đề. Tôi đã kiểm tra nhật ký lỗi và thông báo rằng một tệp đang được tải lên vượt quá kích thước tối đa được phép.
BrightIntelDusk

Câu trả lời:


493

Dưới đây là danh sách kiểm tra để tải lên tệp trong PHP:

  1. Kiểm tra php.ini để biết:
    file_uploads = On
    post_max_size = 100M
    upload_max_filesize = 100M

    • Bạn có thể cần phải sử dụng .htaccesshoặc .user.ininếu bạn đang sử dụng lưu trữ chia sẻ và không có quyền truy cập php.ini.
    • Đảm bảo bạn đang chỉnh sửa tệp ini chính xác - sử dụng phpinfo()chức năng để xác minh cài đặt của bạn đang thực sự được áp dụng.
    • Ngoài ra hãy chắc chắn rằng bạn không đánh vần sai các kích thước - nó phải là 100M không 100MB .
  2. Hãy chắc chắn rằng <form>thẻ của bạn có enctype="multipart/form-data"thuộc tính. Không có thẻ nào khác hoạt động, nó phải là thẻ FORM của bạn. Kiểm tra lại rằng nó được viết đúng chính tả . Kiểm tra kỹ xem nhiều dữ liệu / biểu mẫu dữ liệu được bao quanh bởi STRAIGHT QUOTES, không phải trích dẫn thông minh được dán từ Word HOẶC từ blog của trang web (WordPress chuyển đổi dấu ngoặc kép thành dấu ngoặc kép!). Nếu bạn có nhiều biểu mẫu trên trang, hãy đảm bảo cả hai đều có thuộc tính này. Nhập chúng theo cách thủ công hoặc thử các trích dẫn đơn được nhập bằng tay.

  3. Đảm bảo bạn không có hai trường tệp đầu vào có cùng namethuộc tính. Nếu bạn cần hỗ trợ nhiều, đặt dấu ngoặc vuông ở cuối tên:

    <input type="file" name="files[]">
    <input type="file" name="files[]">
  4. Đảm bảo thư mục tmp và tải lên của bạn có quyền đọc + ghi chính xác được đặt. Thư mục tải lên tạm thời được chỉ định trong cài đặt PHP là upload_tmp_dir.

  5. Đảm bảo đích tệp của bạn và thư mục tmp / tải lên không có khoảng trắng trong chúng.

  6. Đảm bảo tất cả <form>các trang trên trang của bạn đều có </form>thẻ đóng.

  7. Hãy chắc chắn rằng thẻ FORM của bạn có method="POST". Yêu cầu GET không hỗ trợ tải lên nhiều dữ liệu / biểu mẫu.

  8. Đảm bảo thẻ nhập tệp của bạn có thuộc tính NAME. Một thuộc tính ID là không đủ! Các thuộc tính ID được sử dụng trong DOM, không phải cho tải trọng POST.

  9. Hãy chắc chắn rằng bạn không sử dụng Javascript để vô hiệu hóa <input type="file">trường của bạn khi gửi

  10. Hãy chắc chắn rằng bạn không lồng các hình thức như <form><form></form></form>

  11. Kiểm tra cấu trúc HTML của bạn để biết các thẻ không hợp lệ / chồng chéo như <div><form></div></form>

  12. Ngoài ra, hãy đảm bảo rằng tệp bạn đang tải lên không có bất kỳ ký tự không chữ và số nào trong đó.

  13. Một lần, tôi chỉ mất hàng giờ cố gắng để tìm ra lý do tại sao điều này lại xảy ra với tôi một cách đột ngột. Hóa ra tôi đã sửa đổi một số cài đặt PHP trong đó .htaccessvà một trong số chúng (chưa chắc là cái nào) đã khiến quá trình tải lên không thành công và $_FILESbị trống.

  14. Bạn có khả năng có thể thử tránh dấu gạch dưới ( _) trong name=""thuộc tính của <input>thẻ

  15. Hãy thử tải lên các tệp rất nhỏ để thu hẹp xem đó có phải là sự cố kích thước tệp không.

  16. Kiểm tra dung lượng đĩa trống của bạn. Mặc dù rất hiếm, nó được đề cập trong bình luận trang Hướng dẫn PHP này :

    Nếu mảng $ _FILES đột nhiên trống rỗng một cách bí ẩn, mặc dù biểu mẫu của bạn có vẻ đúng, bạn nên kiểm tra dung lượng đĩa có sẵn cho phân vùng thư mục tạm thời của bạn. Trong cài đặt của tôi, tất cả các tệp tải lên không thành công mà không có cảnh báo. Sau nhiều lần nghiến răng, tôi đã cố gắng giải phóng thêm dung lượng, sau đó tệp tải lên đột nhiên hoạt động trở lại.

  17. Hãy chắc chắn rằng bạn không gửi biểu mẫu thông qua yêu cầu AJAX POST thay vì yêu cầu POST thông thường khiến trang tải lại. Tôi đã đi qua từng điểm trong danh sách trên và cuối cùng phát hiện ra rằng lý do mà biến $ _FILES của tôi trống là tôi đã gửi biểu mẫu bằng yêu cầu AJAX POST. Tôi biết rằng cũng có các phương pháp để tải lên các tệp bằng ajax, nhưng đây có thể là một lý do hợp lệ tại sao mảng $ _FILES của bạn trống.

Nguồn cho một số điểm sau:
http://getluky.net/2004/10/04/apachephp-_files-array-mysteriously-empty/


12
Có thể câu trả lời "được chấp nhận" đã giải quyết bài đăng gốc, nhưng câu trả lời này là câu trả lời mà tôi thấy hữu ích nhất. Khi nghi ngờ, hãy nhìn vào nguồn mà trình duyệt nhìn thấy. Kiểm tra từng mục trong danh sách này và truy ngược lại, tôi thấy lỗi của mình ở một nơi không ngờ nhất. Nếu bạn đang vật lộn với một vấn đề tương tự, tin tôi đi, có lẽ đó không phải là một lỗi trong Apache. ;)
quickthyme

3
Ngoài ra, hãy đảm bảo phần tử biểu mẫu của bạn chứa tệp đầu vào KHÔNG phải là phần tử con của phần tử biểu mẫu khác. ví dụ<form><form><input type="file"></form></form>
sudee

3
ồ Cảm ơn bạn vì danh sách này. vấn đề của tôi là # 2. tôi đã gọi $('#my-form')[0].reset();trong trình xử lý trình.
Gavin

2
cảm ơn. trong trường hợp của tôi số 7. enctype = "Multipart / form-data" là thủ phạm.
Thupten

3
DUDE, bạn là một phao cứu sinh. Tôi dành hàng giờ cố gắng để tìm ra điều này (2) là vấn đề của tôi ... Cảm ơn!
Mike Q

74

Theo như HTML bạn xuất hiện đã thiết lập chính xác phần đó. Bạn đã có những enctype="multipart/form-data"thứ rất quan trọng để có trong mẫu.

Theo như php.inithiết lập của bạn , đôi khi trên các hệ thống php.initồn tại nhiều tệp. Hãy chắc chắn rằng bạn đang chỉnh sửa đúng. Tôi biết bạn nói rằng bạn đã cấu hình php.initệp của mình để tải lên tệp, nhưng bạn cũng đã đặt tệp của mình upload_max_filesizepost_max_sizelớn hơn tệp bạn đang cố tải lên chưa? Vì vậy, bạn nên có:

file_uploads = On; sounds like you already did this
post_max_size = 8M; change this higher if needed
upload_max_filesize = 8M; change this higher if needed

Thư mục của bạn: "c:\wamp\tmp"có cả quyền đọc và ghi không? Bạn có nhớ khởi động lại Apache sau khi bạn thực hiện các php.inithay đổi không?



4
+1: Để khởi động lại mẹo máy chủ Apache. Nhiều người dùng Windows quên điều đó.
shamittomar

36

Điều quan trọng là thêm enctype="multipart/form-data"vào mẫu của bạn, ví dụ

<form action="upload.php" method="post" enctype="multipart/form-data">
    Select image to upload:
    <input type="file" name="fileToUpload" id="fileToUpload">
    <input type="submit" value="Upload Image" name="submit">
</form>

14

Cảm ơn tất cả mọi người vì đã trả lời toàn diện. Đó là tất cả rất hữu ích. Câu trả lời hóa ra là một cái gì đó rất kỳ quặc. Hóa ra PHP 5.2.11 không giống như sau:

post_max_size = 2G

hoặc là

post_max_size = 2048M

Nếu tôi thay đổi nó 2047M, tải lên hoạt động.


17
Lưu ý rằng giá trị cao như vậy là một lỗ hổng cho các cuộc tấn công ngoài không gian / ddos. Chỉ cần thêm điều này để mọi người nhận ra nó quá nhiều, khi họ cố gắng sao chép và dán giải pháp của bạn. Dù sao, 2 hợp đồng biểu diễn sẽ yêu cầu thời gian tải lên quá dài.
Manuel Arwed Schmidt

Không quá lớn nữa. Chúng tôi có những khách hàng tải lên các tệp trong phạm vi 1-3G khá thường xuyên. Vì họ đang tải tệp lên máy chủ của chính họ và họ là máy chủ có danh sách trắng IP, việc trao đổi là khá bình thường và chỉ là cách cho phép khách hàng sử dụng thiết bị của họ theo cách họ muốn sử dụng. Họ trả các hóa đơn, không có rủi ro bảo mật liên quan, không có vấn đề.
TheSatinKnight

8

Tôi có một vấn đề tương tự tìm kiếm 2 giờ, rất đơn giản để chúng tôi kiểm tra cấu hình máy chủ của chúng tôi đầu tiên.

Thí dụ:

echo $upload_max_size = ini_get('upload_max_filesize');  
echo $post_max_size=ini_get('post_max_size');   

bất kỳ loại kích thước tập tin là :20mb, nhưng của chúng tôi upload_max_sizeở trên 20mbnhưng mảng là null. Trả lời là của chúng tôi post_max_sizenên lớn hơn upload_max_filesize

post_max_size = 750M  
upload_max_filesize = 750M

6

Ở đây, một nguyên nhân khác mà tôi tìm thấy: Khi sử dụng JQuery Mobile và dữ liệu thuộc tính biểu mẫu-ajax được đặt thành true, mảng FILES sẽ trống. Vì vậy, đặt dữ liệu-ajax thành false.


5

Đảm bảo yếu tố đầu vào của bạn có thuộc tính 'name'. <input type="file" name="uploadedfile" />

Nếu điều này bị thiếu, $ _FILES sẽ trống.


4

Tôi đã vật lộn với cùng một vấn đề và kiểm tra mọi thứ, không nhận được báo cáo lỗi và dường như không có gì sai. Tôi đã có lỗi numporting (E_ALL) Nhưng đột nhiên tôi nhận ra rằng tôi đã không kiểm tra nhật ký apache và voilà! Có lỗi cú pháp trên tập lệnh ...! (thiếu "}")

Vì vậy, mặc dù đây là một thứ hiển nhiên cần kiểm tra, nó có thể bị lãng quên ... Trong trường hợp của tôi (linux), nó nằm ở:

/var/log/apache2/error.log

3

Không ai đề cập đến điều này nhưng nó đã giúp tôi ra ngoài và không có nhiều nơi trên mạng đề cập đến nó.

Đảm bảo php.ini của bạn đặt khóa sau:

    upload_tmp_dir="/path/to/some/tmp/folder"

Bạn sẽ cần kiểm tra với webhost của mình nếu họ muốn bạn sử dụng đường dẫn tệp máy chủ tuyệt đối. Bạn sẽ có thể xem các ví dụ thư mục khác trong tệp php.ini của mình để xác định điều này. Ngay khi tôi đặt nó, tôi đã nhận được các giá trị trong đối tượng _FILES của mình.

Cuối cùng hãy đảm bảo rằng thư mục tmp của bạn và bất cứ nơi nào bạn đang di chuyển tệp để có quyền chính xác để chúng có thể được đọc và ghi vào.


2

Nếu bạn đang cố gắng để tải lên một mảng các file sau đó bạn có thể cần phải tăng max_file_uploadstrong php.iniđó là do thiết lập mặc định để20

Lưu ý : max_file_uploadsKHÔNG thể thay đổi bên ngoài php.ini. Xem "Lỗi" PHP # 50684


2

Một thủ phạm có thể là chuyển hướng apache. Trong trường hợp của tôi, tôi đã cài đặt httpd.conf của apache để chuyển hướng một số trang nhất định trên trang web của chúng tôi sang phiên bản http và các trang khác sang phiên bản https của trang, nếu chúng chưa có. Trang mà tôi có một biểu mẫu với đầu vào tệp là một trong những trang được định cấu hình để buộc ssl, nhưng trang được chỉ định là hành động của biểu mẫu được định cấu hình là http. Vì vậy, trang sẽ gửi tải lên phiên bản ssl của trang hành động, nhưng apache đã chuyển hướng nó sang phiên bản http của trang và dữ liệu bài đăng, bao gồm cả tệp đã tải lên bị mất.



1

Nếu tập lệnh chính của bạn là http://Some_long_URL/index.phpcẩn thận để chỉ định URL đầy đủ (với rõ ràng index.phpkhông chỉ http://Some_long_URL) trong actiontrường. Đáng ngạc nhiên, nếu không, tập lệnh đúng được thực thi, nhưng với en $ _FILES trống!


1

Tôi gặp vấn đề tương tự và thấy rằng đó là IDE của tôi là một phần của vấn đề. Tôi đã khởi chạy trình gỡ lỗi trực tiếp từ IDE (PHPStorm) thay vì chỉ sử dụng trình duyệt trực tiếp. URL sinh ra IDE là như thế này:

"...localhost:63342/CB_Upload/index.php?_ijt=j2hcbacqepj87bvg66ncuohvne"

và chỉ sử dụng:

"...localhost/CB_Upload/index.php"

làm việc tốt Thiết lập của tôi là PC / Windows 10 / WAMPSERVER 3.0.6 64 bit


điều tương tự ở đây, tôi đã chạy trong vòng tròn trong một giờ cho đến nay! cảm ơn
EKanadily

1

Không tin tưởng vị trí thư mục tạm thời được cung cấp bởi sys_get_temp_dirnếu bạn đang ở trong môi trường lưu trữ được chia sẻ.

Đây là một điều nữa để kiểm tra mà chưa được đề cập ...

Tôi giả định, một cách tự nhiên, thư mục nơi tập lệnh PHP của tôi lưu trữ các tệp tải lên tạm thời là /tmp. Niềm tin này đã được củng cố bởi thực tế là echo sys_get_temp_dir() . PHP_EOL;trở lại /tmp. Ngoài ra, echo ini_get('upload_tmp_dir');không trả lại gì cả.

Để xác minh rằng tệp đã tải lên thực tế xuất hiện nhanh trong /tmpthư mục của tôi , tôi đã thêm một sleep(30);câu lệnh vào tập lệnh của mình (như được đề xuất ở đây ) và điều hướng đến /tmpthư mục của tôi trong Trình quản lý tệp cPanel để định vị tệp. Tuy nhiên, không có vấn đề gì, tập tin đã tải lên không tìm thấy ở đó.

Tôi đã dành hàng giờ cố gắng để xác định lý do cho việc này và thực hiện mọi đề xuất được đưa ra ở đây.

Cuối cùng, sau khi tìm kiếm các tập tin trang web của tôi để tìm truy vấn tmp, tôi phát hiện ra rằng trang web của tôi chứa các thư mục khác có tên tmptrong các thư mục khác nhau. Tôi nhận ra rằng tập lệnh PHP của tôi thực sự đang viết các tệp được tải lên .cagefs/tmp. ( Cài đặt "Hiển thị tệp ẩn" phải được bật trong cPanel để xem thư mục này.)

Vậy, tại sao sys_get_temp_dirhàm trả về thông tin không chính xác?

Dưới đây là lời giải thích từ trang web PHP.net cho sys_get_temp_dir(ví dụ: bình luận hàng đầu):

Nếu chạy trên hệ thống Linux có systemd có PrivateTmp = true (là mặc định trên CentOS 7 và có lẽ các bản phát hành mới hơn), thì hàm này sẽ chỉ trả về "/ tmp", không phải là đường dẫn động, hơi dài, đúng, dài hơn nhiều.

Bài viết SO này cũng đi sâu vào vấn đề:


0

Tôi gặp vấn đề tương tự và không có chủ đề nào là lỗi của tôi. Kiểm tra tệp .htaccess của bạn, nếu bạn có, nếu "MultiViews" được bật. Tôi đã phải vô hiệu hóa chúng.


0

Tôi đã có vấn đề tương tự và vấn đề là giá trị sai trong htaccess như shamittomar đã đề cập.

Thay đổi php_value post_max_size 10MBthànhphp_value post_max_size 10M


0

Tôi đã trống rỗng $_FILESvì sau khi <form enctype="multipart/form-data" method="post">tôi đặt

</div>
<div style="clear:both"></div>

Mã ban đầu giống như

<span class="span_left">Photos (gif/jpg/jpeg/png) </span>
<form enctype="multipart/form-data" method="post">
<input name="files[]" type="file" id="upload_file" />
<input type="button" id="upload" value="Upload photo" />
</form>

Tôi quyết định sửa đổi và

<div>
<span class="span_left">Photos (gif/jpg/jpeg/png) </span>
<form enctype="multipart/form-data" method="post">
</div>
<div style="clear:both"></div>
<input name="files[]" type="file" id="upload_file" />
<input type="button" id="upload" value="Upload photo" />
</form>
<div style="clear:both"></div>

Vì vậy, kết luận là sau <form enctype="multipart/form-data" method="post">phải <input name, type, idvà không được <div>hoặc một số thẻ khác

Trong tình huống của tôi, mã chính xác là

<div>
<span class="span_left">Photos (gif/jpg/jpeg/png) </span>
</div>
<div style="clear:both"></div>
<form enctype="multipart/form-data" method="post">
<input name="files[]" type="file" id="upload_file" />
<input type="button" id="upload" value="Upload photo" />
</form>
<div style="clear:both"></div>

0

Tôi cũng có vấn đề với $ _FILES trống. Danh sách kiểm tra ở trên không đề cập đến MultiViews trong .htaccess, httpd.conf hoặc httpd-vhost.conf.

Nếu bạn có MultiViews được đặt trong chỉ thị tùy chọn cho thư mục chứa trang web, $ _FILES sẽ trống, ngay cả tiêu đề Độ dài nội dung nếu hiển thị rằng tệp tôi đã tải lên.


0

Nếu bạn đang sử dụng JQuery Mobile

Sử dụng một hình thức nhiều phần với một đầu vào tệp không được Ajax hỗ trợ. Trong trường hợp này, bạn nên trang trí biểu mẫu gốc bằng data-ajax = "false" để đảm bảo biểu mẫu được gửi đúng đến máy chủ.

<form action="upload.php" method="post" enctype="multipart/form-data"  data-ajax="false">
    Select image to upload:
    <input type="file" name="fileToUpload" id="fileToUpload">
    <input type="submit" value="Upload Image" name="submit">
</form>

0

Tách biểu mẫu của bạn từ trang bạn đang sử dụng thành một trang php đơn giản chỉ có biểu mẫu và mã php và kiểm tra nó như thế.

Bất kỳ tập lệnh bootstrap hoặc java nào cũng có thể xóa sạch _FILES []. Đó là trường hợp của tôi

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.