Чому $ _FILES буде порожнім під час завантаження файлів на PHP?


145

У мене на комп'ютері Windows 7 встановлений WampServer 2. Я використовую Apache 2.2.11 та PHP 5.2.11. Коли я намагаюся завантажити будь-який файл із форми, здається, він завантажується, але в PHP $_FILESмасив порожній. У c:\wamp\tmpпапці немає файлу . Я налаштував, php.iniщоб дозволити завантаження файлів тощо. tmpПапка привілеї читання / запису для поточного користувача. Я тупаю.

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
Ви перевірили журнали помилок?
Байрон Вітлок

Я впевнений, що є щось німе, що ви не помічаєте. Наприклад, ви впевнені, що код маєте vanilla-upload.php?
Лука Маттейс

Ха у мене була така ж проблема. Я перевірив журнали помилок, і він сказав, що завантажується файл, що перевищує максимально допустимий розмір.
BrightIntelDusk

Відповіді:


493

Ось контрольний список для завантаження файлів у PHP:

  1. Перевірте php.ini на:
    file_uploads = On
    post_max_size = 100M
    upload_max_filesize = 100M

    • Можливо, вам доведеться використовувати .htaccessабо .user.iniякщо ви перебуваєте на спільному хостингу і не маєте доступу до нього php.ini.
    • Переконайтесь, що ви редагуєте правильний файл ini - скористайтеся phpinfo()функцією, щоб перевірити, чи налаштовані ваші налаштування.
    • Крім того, переконайтеся , що ви не робити орфографічні помилки розміри - він повинен бути 100M НЕ 100MB .
  2. Переконайтеся, що ваш <form>тег має enctype="multipart/form-data"атрибут. Жоден інший тег не буде працювати, він повинен бути вашим тегом FORM. Перевірте, чи правильно написано . Перевірте, чи багаточастинні / форми даних оточені ПРАВИМИМИ ЦИТАТАМИ, а не розумні цитати, вставлені з Word OR АБО з блогу веб-сайту (WordPress перетворює прямі лапки в кутові лапки!). Якщо у вас є кілька форм на сторінці, переконайтеся, що вони мають цей атрибут. Введіть їх вручну або спробуйте окремі цитати, введені вручну.

  3. Переконайтеся, що у вас немає двох полів вхідного файлу з однаковим nameатрибутом. Якщо вам потрібно підтримати декілька, поставте квадратні дужки в кінці назви:

    <input type="file" name="files[]">
    <input type="file" name="files[]">
  4. Переконайтеся, що у ваших каталогах tmp та upload встановлені правильні дозволи на читання та запис. Тимчасова папка завантаження вказана в настройках PHP як upload_tmp_dir.

  5. Переконайтесь, що у файлі призначення та в каталогах tmp / upload немає пробілів.

  6. Переконайтесь, що всі <form>на вашій сторінці мають </form>тісні теги.

  7. Переконайтеся, що ваш тег FORM має method="POST". GET-запити не підтримують завантаження даних із кількох частин / форм.

  8. Переконайтесь, що ваш тег введення файлу має атрибут NAME. Атрибут ID НЕ достатній! Атрибути ID призначені для використання в DOM, а не для корисних навантажень POST.

  9. Переконайтеся, що ви не використовуєте Javascript для відключення <input type="file"> поля під час подання

  10. Переконайтеся, що ви не вкладаєте такі форми, як <form><form></form></form>

  11. Перевірте свою HTML-структуру на наявність недійсних / перекриваються тегів, як-от <div><form></div></form>

  12. Також переконайтесь, що файл, який ви завантажуєте, не містить в ньому не буквено-цифрових символів.

  13. Одного разу я просто провів години, намагаючись з’ясувати, чому це сталося зі мною раптом. Виявилося, що я змінив деякі налаштування PHP .htaccess, і один із них (не впевнений, який ще) спричинив невдачу завантаження та $_FILESпорожній.

  14. Ви можете потенційно спробувати уникнути підкреслення ( _) в name=""атрибуті <input>тегу

  15. Спробуйте завантажити дуже маленькі файли, щоб звузити, чи це проблема розміру файлу.

  16. Перевірте наявне місце на диску. Хоча це дуже рідко, він згадується в коментарі на сторінці PHP-інструкції :

    Якщо масив $ _FILES раптом загадково порожній, хоча форма видається правильною, слід перевірити місце на диску для вашого тимчасового розділу. У моїй установці не вдалося завантажити всі файли без попередження. Після довгого скреготування зубів я спробував звільнити додатковий простір, після чого завантаження файлів раптово знову працювало.

  17. Будьте впевнені, що ви не надсилаєте форму через запит AJAX POST замість звичайного запиту POST, який спричиняє перезавантаження сторінки. Я переглянув кожну точку списку вище і, нарешті, з’ясував, що причиною, через яку моя змінна $ _FILES порожня, було те, що я надсилав форму за допомогою запиту AJAX POST. Я знаю, що існують також методи завантаження файлів за допомогою ajax, але це може бути вагомою причиною того, що масив $ _FILES порожній.

Джерело для деяких із цих пунктів:
http://getluky.net/2004/10/04/apachephp-_files-array-mysteriously-empty/


12
Можливо, "прийнята" відповідь вирішила оригінальний пост, але ця відповідь виявилася мені найбільш корисною. Коли ви сумніваєтесь, подивіться на джерело, яке бачить браузер. Перевіряючи кожен елемент у цьому списку та відстежуючи відсталість, я виявив свою помилку в самому несподіваному місці. Якщо ви боретеся з подібною проблемою, повірте, це, мабуть, не помилка в Apache. ;)
швидкодію

3
Також переконайтесь, що елемент форми, що містить вхід файлу, НЕ є дочірнім для іншого елемента форми. наприклад<form><form><input type="file"></form></form>
sudee

3
Оце Так! дякую за цей список моя проблема була №2. я дзвонив $('#my-form')[0].reset();в обробник подання.
Гевін

2
Дякую. у моєму випадку №7. enctype = "multipart / form-data" винуватцем.
Тюптен

3
ДУДЕ, ти рятівник. Я витрачав години, намагаючись розібратися в цьому (2), було моєю проблемою ... Дякую!
Майк Q

74

Щодо HTML, який, здається, правильно налаштував цю частину. У вас вже єenctype="multipart/form-data" що дуже важливо мати на формі.

Що стосується вашої php.iniнастройки, іноді в системах php.iniіснує кілька файлів. Будьте впевнені, що ви редагуєте правильний. Я знаю, ви сказали, що ви налаштували свій php.iniфайл на завантаження файлів, але ви також встановили свій upload_max_filesizeі post_max_sizeбути більшим за файл, який ви намагаєтеся завантажити? Отже, ви повинні мати:

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

Чи має ваш каталог: чи "c:\wamp\tmp"є дозволи на читання та запис? Чи пам’ятали ви перезапустити Apache після внесення php.iniзмін?



4
+1: для перезавантаження підказки сервера Apache. Багато користувачів Windows це забувають.
shamittomar

36

Важливо додати enctype="multipart/form-data"до своєї форми, наприклад

<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

Дякую всім за різні вичерпні відповіді. Все це дуже корисно. Відповідь виявилася чимось дуже дивним. Виявляється, PHP 5.2.11 не любить наступне:

post_max_size = 2G

або

post_max_size = 2048M

Якщо я зміню його 2047M, завантаження працює.


17
Зауважте, що таке високе значення є вразливістю до атак поза космосом / ddos. Просто додаючи це, щоб люди занадто багато усвідомлювали його, коли намагаються скопіювати та вставити ваше рішення. У будь-якому випадку, для 2 концертів потрібен час завантаження, який занадто довгий.
Мануель Арвед Шмідт

Не надто великий уже. У нас є клієнти, які доволі регулярно завантажують файли в діапазоні 1-3G. Оскільки вони завантажують файли на свої власні сервери і вони є білими серверами IP, обмін є цілком нормальним і просто способом дозволити клієнту використовувати своє обладнання так, як він хоче ним користуватися. Вони сплачують рахунки, не загрожує безпеці, немає проблем.
TheSatinKnight

8

У мене така ж проблема 2 години, дуже просто перевірити конфігурацію нашого сервера.

Приклад:

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

будь-який розмір файлу є :20mb, але наш upload_max_sizeвище, 20mbале масив є null. Відповідь нашої post_max_sizeповинна бути більшою, ніж upload_max_filesize

post_max_size = 750M  
upload_max_filesize = 750M

6

Ось ще одна причина, яку я знайшов: Коли для використання JQuery Mobile і атрибуту форми data-ajax встановлено значення true, масив FILES буде порожнім. Тому встановіть дані-ajax на значення false.


5

Переконайтеся, що у вхідного елемента є атрибут 'name'. <input type="file" name="uploadedfile" />

Якщо цього немає, $ _FILES буде порожнім.


4

Я боровся з тією самою проблемою і тестував усе, не отримував повідомлення про помилки і нічого, здавалося, не так. Я мав повідомлення про помилки (E_ALL) Але раптом я зрозумів, що не перевірив журнал apache та voilà! У скрипті сталася помилка синтаксису ...! (відсутній "}")

Тож, хоч це щось очевидне для перевірки, це можна забути ... У моєму випадку (linux) це за адресою:

/var/log/apache2/error.log

3

Ніхто про це не згадував, але це мені допомогло, і не багато місця в мережі згадують про це.

Переконайтеся, що ваш php.ini встановлює таку клавішу:

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

Вам потрібно буде перевірити у своєму веб-хості, чи хочуть вони використовувати абсолютний шлях до файлу сервера. Ви повинні мати можливість бачити інші приклади каталогів у вашому файлі php.ini, щоб визначити це. Як тільки я його встановив, я отримав значення в моєму об'єкті _FILES.

Нарешті переконайтесь, що у вашій папці tmp та в будь-якому місці ви переміщуєте файли, щоб вони мали правильні дозволи, щоб їх можна було читати та писати.


2

Якщо ви намагаєтеся завантажити масив файлів , то вам , можливо , доведеться збільшити max_file_uploadsв php.iniякий за замовчуванням задано20

Примітка : max_file_uploadsНЕ можна змінювати за межами php.ini. Див. PHP "Помилка" # 50684


2

Ще один можливий винуватець - це перенаправлення apache. У моєму випадку у мене був httpd.conf апачі, налаштований перенаправляти певні сторінки на нашому веб-сайті до версій http, а інші сторінки до https-версій сторінки, якщо вони ще не були. Сторінка, на якій у мене була форма з введенням файлу, була однією зі сторінок, налаштованих для змушування ssl, але сторінка, позначена як дія форми, була налаштована як http. Таким чином, сторінка надсилатиме завантаження до версії ssl сторінки дії, але apache перенаправляє її до http-версії сторінки, а дані публікації, включаючи завантажений файл, втрачаються.


2

Перевірте свій php.ini на enable_post_data_reading = Увімкнено , оскільки:

Якщо вимкнути цю опцію, параметри $ _POST та $ _FILES не заповнюються . Єдиним способом читання публікацій буде через прошивку вхідного потоку php: //. (...)

В http://php.net/manual/en/ini.core.php#ini.enable-post-data-reading


1

Якщо ваш головний сценарій http://Some_long_URL/index.phpобережно, вкажіть у полі повну URL-адресу (з явним index.phpі не тільки http://Some_long_URL) action. Дивно, якщо ні, правильний сценарій виконується, але з порожнім $ _FILES!


1

Я зіткнувся з тим самим номером і виявив, що саме моя IDE була частиною випуску. Я запускав налагоджувач безпосередньо з IDE (PHPStorm), а не просто використовував браузер. Ідентифікована URL-адреса IDE була такою:

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

і просто використовуючи:

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

працював просто чудово. Моя настройка - PC / Windows 10 / WAMPSERVER 3.0.6 64bit


те саме, що я бігав по колу протягом години! спасибі
EKanadily

1

Не довіряйте розташуванню папки temp, яке надає компанія sys_get_temp_dir якщо ви перебуваєте у спільному хостингу.

Ось ще одна річ, щоб перевірити, що ще не було згадано ...

Природно, я припустив, що папка, в якій зберігався мій тимчасовий скрипт PHP, була /tmp. Ця віра була підкріплена тим, що echo sys_get_temp_dir() . PHP_EOL;повертається /tmp. Також,echo ini_get('upload_tmp_dir'); нічого не повертає.

Щоб переконатися, що завантажений файл насправді коротко відображається у моїй /tmpпапці, я додав sleep(30);заяву до свого сценарію (як тут запропоновано ) та перейшов до мого/tmp папки в cPanel File Manager, щоб знайти файл. Однак, незважаючи ні на що, завантажений файл ніде не було знайдено.

Я витратив години, намагаючись визначити причину цього, і втілив усі запропоновані тут пропозиції.

Нарешті, після пошуку файлів мого веб-сайту для запиту tmp, я виявив, що мій сайт містить інші папки, названі tmpв різних каталогах. Я зрозумів, що мій сценарій PHP насправді записує завантажені файли .cagefs/tmp. ( "Показати приховані файли" Щоб переглянути цю папку, в cPanel потрібно включити налаштування .)

Отже, чому sys_get_temp_dirфункція повертає неточну інформацію?

Ось пояснення з веб-сторінки PHP.net щодо sys_get_temp_dir(тобто верхній коментар):

Якщо працює в системі Linux, де systemd має PrivateTmp = true (що є типовим для CentOS 7 та, можливо, іншими новішими дистрибутивами), ця функція просто поверне «/ tmp», не справжній, набагато довший, дещо динамічний шлях.

Ця публікація ТА також заглиблюється у випуск:


0

У мене така ж проблема, і жодна тема не була моєю помилкою. Перевірте свій файл .htaccess, якщо він у вас є, якщо "MultiViews" увімкнено. Мені довелося їх відключити.


0

У мене була аналогічна проблема, і ця проблема мала неправильне значення в htaccess, як згадував shamittomar.

Змінити php_value post_max_size 10MBнаphp_value post_max_size 10M


0

Я був порожній, $_FILESтому що після того, як <form enctype="multipart/form-data" method="post">я розмістив

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

Початковий код був таким

<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>

Я вирішив модифікувати і

<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>

Отже, висновок полягає в тому, що після <form enctype="multipart/form-data" method="post">повинні бути <input name, type, idі не повинні бути <div>або якісь інші теги

У моїй ситуації правильний код був

<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

У мене теж були проблеми з порожнім $ _FILES. У наведеному вище контрольному списку не згадуються MultiViews в .htaccess, httpd.conf або httpd-vhost.conf.

Якщо у директиві параметрів для вашого каталогу, що містить веб-сайт, встановлено MultiViews, $ _FILES буде порожнім, навіть незважаючи на те, що заголовок довжини вмісту показує, що файл завантажений я.


0

Якщо ви використовуєте JQuery Mobile

Використання багаточастинкової форми з введенням файлу Ajax не підтримує. У цьому випадку слід прикрасити батьківську форму data-ajax = "false", щоб переконатися, що форма належним чином подана на сервер.

<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

Виділіть форму своєї сторінки, яку ви використовуєте, на просту сторінку PHP, яка має лише форму та php-код, і протестуйте її так.

Будь-який сценарій завантаження або java-сценарій може очистити _FILES []. Це був мій випадок

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.