Почему $ _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. Дважды проверьте, что оно написано правильно . Дважды проверьте, что multipart / form-data окружены прямыми цитатами, а не умными цитатами, вставленными из 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-запросы не поддерживают загрузку данных multipart / form-data.

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

    Если массив $ _FILES внезапно загадочным образом становится пустым, даже если ваша форма кажется правильной, вам следует проверить дисковое пространство, доступное для вашего раздела временной папки. В моей установке все загрузки файлов не прошли без предупреждения. После большого скрежета зубов я попытался освободить дополнительное пространство, после чего загрузка файлов неожиданно снова заработала.

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

Источник для некоторых из этих пунктов:
http://getluky.net/2004/10/04/apachephp-_files-array-mysteriously-empty/


12
Может быть, «принятый» ответ решил исходное сообщение, но этот ответ я нашел наиболее полезным. Если вы сомневаетесь, посмотрите на источник в браузере. Отметив каждый элемент в этом списке и проследив его в обратном направлении, я обнаружил свою ошибку в самом неожиданном месте. Если вы боретесь с подобной проблемой, поверьте мне, это, вероятно, не ошибка в Apache. ;)
quickthyme

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

3
Вот Это Да! спасибо за этот список. моя проблема была №2. я звонил $('#my-form')[0].reset();в обработчике отправки.
Гэвин

2
Спасибо. в моем случае № 7. виновником был enctype = "multipart / form-data".
Thupten

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 забывают об этом.
Шамтомар

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 будет пустым. Так что установите data-ajax в false.


5

Убедитесь, что ваш входной элемент имеет атрибут name. <input type="file" name="uploadedfile" />

Если это отсутствует, $ _FILES будет пустым.


4

Я боролся с той же проблемой и все тестировал, не получал сообщений об ошибках, и, похоже, все было в порядке. У меня был error_reporting (E_ALL), но внезапно я понял, что я не проверил журнал apache и вуаля! Произошла синтаксическая ошибка в сценарии ...! (отсутствует "}")

Таким образом, хотя это и нужно проверить, это можно забыть ... В моем случае (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. В моем случае у меня был настроен apache httpd.conf для перенаправления определенных страниц нашего сайта в версии http, а другие страницы в версии https, если они еще не были. Страница, на которой у меня была форма с вводом файла, была одной из страниц, настроенных для принудительного использования ssl, но страница, обозначенная как действие формы, была настроена на http. Таким образом, страница отправляла закачку в ssl-версию страницы действия, но apache перенаправлял ее на http-версию страницы, и данные публикации, включая загруженный файл, были потеряны.


2

Проверьте ваш php.ini на наличие enable_post_data_reading = On , потому что:

Отключение этой опции приводит к тому, что $ _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"

работал просто отлично. Моя установка - ПК / Windows 10 / WAMPSERVER 3.0.6 64bit


то же самое здесь, я бегал кругами целый час! спасибо
EKanadily

1

Не доверяйте расположению временной папки, предоставленной, 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, чтобы найти файл. Однако, несмотря ни на что, загруженный файл нигде не был там найден.

Я потратил часы, пытаясь определить причину этого, и реализовал каждое предложение, которое было предложено здесь.

Наконец, после поиска файлов моего сайта для запроса 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.

Если в директиве опций для вашего каталога, содержащего веб-сайт, установлены MultiView, $ _FILES будет пустым, даже если заголовок Content-Length отображает загруженный файл.


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.