Загрузка PHP - 500 Внутренняя ошибка сервера
Проблема
При загрузке файлов размером около 8 МБ или более я получаю 500 внутренних ошибок сервера.
- Все настройки PHP в
php.ini
верны -
maxAllowedContentLength
был установлен в файле web.config
Информация о сервере
Как, вероятно, можно судить по maxAllowedContentLength
, я запускаю IIS 7.5 с FastCGI и PHP 5.3.17
Дополнительная информация
Я перепробовал так много разных вещей, чтобы заставить это работать, но просто не могу найдите проблему.
Тем не менее, я нашел следующие фрагменты информации, которые могут помочь выяснить причину этой проблемы:
- При загрузке файлов (больших) с помощью медиа-Вики, которая у меня есть на сервере, я получаю ту же ошибку, это показывает, что это не ошибка в моем коде.
- Самое главное - Мне удалось загрузить файл размером 18 МБ в файловый менеджер Plesk, это, очевидно, означает, что Plesk смог обойти эту проблему конфигурации. У меня есть попытался скопировать все настройки панели управления Plesk в этот домен в IIS, но это, похоже, не работает.
- Ошибка возвращается до выполнения сценария, так как я попытался написать
exit;
вверху, чтобы попытаться получить пустой экран, но это игнорируется и возвращается ошибка 500.
Я думаю, что проблема заключается в configure command
части конфигурации PHP, потому что, когда я изменяю отображение обработчика файлов .php
, чтобы использовать Pleskphp-cgi.exe
вместо обычного я не получаю внутреннюю ошибку 500. Сказав это, я не могу оставить его на этой версии PHP, так как это собственная версия Plesk exe
и есть другие проблемы с конфигурацией.
Причина, по которой я думаю, что это может быть связано с командой configure, заключается просто в том, что это сильно отличается от одного phpinfo()
к другому.
Если у вас есть какие-либо идеи или предложения, пожалуйста, опубликуйте их. Я перепробовал все, что знал, и, похоже, не могу это исправить. Если бы только это было Linux...
Заранее благодарю
ОБНОВЛЕНИЕ 1
Забыл добавить, что в журнале ошибок PHP нет возвращаемых ошибок. Что касается ошибок IIS, я не знаю, где искать
ОБНОВЛЕНИЕ 2
Вот что я поместил в свой файл web.config
:
<security>
<requestFiltering>
<requestLimits maxAllowedContentLength="2147483647" />
</requestFiltering>
</security>
ОБНОВЛЕНИЕ 3
С вашей помощью нам удалось получить сообщение об ошибке, отображаемое IIS. Вот что я получаю:
Предупреждение PHP: СООБЩЕНИЕ Содержимое -Длина 12221448 байт превышает предельное значение из 8388608 байт в неизвестном в строке 0
Это связано с post_max_size
?
ОБНОВЛЕНИЕ 4
Настройки PHP следующим образом (из phpinfo()
):
post_max_size = 64M memory_limit = 128M max_file_uploads = 20 max_execution_time = 6000 upload_max_filesize = 64M
ОБНОВЛЕНИЕ 5
Наконец, на всякий случай, если кто-нибудь сможет обнаружить какие-либо потенциальные проблемы, Plesk может абсолютно нормально загружать большие файлы, поэтому я предположил, что их php-cgi.exe был составлен по-другому. Когда я читаю phpinfo() из их конфигурация информация configure command
была очень разной:
Моя конфигурация:
Cscript /нолого configure.js "--включить-создание моментального снимка" "--отключить-isapi" "--включить-отладочный пакет" "--без-mssql" "--без-pdo-mssql" "--без-pi3web" "--with-pdo-oci=C:\php-sdk\oracle\instantclient10\sdk, общий доступ" "--with-oci8=C:\php-sdk\oracle\instantclient10\sdk, общий доступ" "--with-oci8-11g=C:\php-sdk\oracle\instantclient11\sdk, общий доступ" "--включить-объект-выход-реж=../obj/" "--включить-com-dotnet=общий доступ" "--with-mcrypt=статический" "--отключить-статический-анализ"
Конфигурация Plesk:
Cscript /нолого configure.js "--включить-отладку-пакет" "--включить-интерфейс командной строки" "--включить-cgi" "--включить-isapi" "--включить-один выстрел" "--включить-pdo" "--включить-intl" "--с-openssl=общий доступ" "--с-pdo-odbc" "--с-iconv" "--с-xml" "--с-xsl" "--с-mysql" "--с помощью-mysqlnd" "--с помощью-mysqli" "--с помощью-pdo-sqlite" "--с-pdo-mysql" "--с-curl=общий доступ" "--включить-mbstring" "--включить-mbregex" "--с-imap=общий доступ" "--включить-сокеты" "--включить-шмоп" "--включить-мыло"
ОБНОВЛЕНИЕ (ОТВЕТ)
Это чрезвычайно странно, так как информация phpinfo()
говорит об одном, но ее явно игнорируют, не знаю почему.
Если я изменю post_max_size
в Plesk для этого конкретного домена/поддомена, то ничего не изменится (хотя, похоже, это изменилось в phpinfo()
). Однако, если я действительно изменю post_max_value
в php.ini затем это устраняет проблему.
Причина, по которой это не лучший способ исправить это, заключается просто в том, что при обновлении Plesk php.ini перезаписывается по мере обновления PHP, и в результате изменения, внесенные в php.ini, теряются. Это означает, что каждый раз, когда Plesk обновляет, мне нужно будет вносить изменения в php.ini. Вот почему Plesk предлагает возможность изменять настройки PHP без внесения изменений в php.ini.
Кто-нибудь может подумать о том, почему PHP игнорирует локальное значение и возвращаясь к значению в php.ini, даже если в php.ini указано, что локальное значение отличается?
4 answers
Если вы посмотрите на исходный код PHP, вы можете увидеть в файле php-5.4.8-src\main\rfc1867.c
строку 706-709 следующее:
if (SG(post_max_size) > 0 && SG(request_info).content_length > SG(post_max_size)) {
sapi_module.sapi_error(E_WARNING, "POST Content-Length of %ld bytes exceeds the limit of %ld bytes", SG(request_info).content_length, SG(post_max_size));
return;
}
То же самое есть и в файле php-5.4.8-src\main\SAPI.c
.
Итак, сообщение PHP Warning: POST Content-Length of 12221448 bytes exceeds the limit of 8388608 bytes in Unknown on line 0
касается настройки post_max_size. Вы подтвердили с помощью phpinfo(), что этот параметр настроен правильно, но, похоже, он все равно использует значение по умолчанию 8M.
Почему, смотрите в этой теме:
Как оказалось, в Windows вы можете установить только ini директивы, помеченные
PHP_INI_USER
для каждого каталога. К несчастью,upload_max_filesize
иpost_max_size
оба являютсяPHP_INI_PERDIR
. Из документов PHP на http://php.net/manual/en/configuration.changes.phpНастройки каталога будут активны для любого сценария, запущенного из этого каталога или любого его подкаталога. Ценности под ключом должно быть имя директивы конфигурации PHP и строковое значение. Константы PHP в значениях не анализируются. Однако таким образом можно задать только значения конфигурации, изменяемые в PHP_INI_USER, значения PHP_INI_PERDIR не могут.
Таким образом, несмотря на то, что у Plesk есть интерфейс для изменения этих директив, и даже несмотря на то, что
phpinfo()
улавливает их, они ничего не меняют фактические максимальные размеры загрузки. Plesk не должен позволять вам изменять те, что в Windows, иphpinfo()
не должны сообщать об изменении, но что вы можете сделать.
Итак, это post_max_size, и он должен быть установлен на php.ini. Настройка Plesk просто не будет работать, даже если phpinfo говорит об обратном. Я также открыл запись об ошибке в поведении phpinfo, поскольку, похоже, для нее не было записи.
Это довольно распространенная ошибка и происходит из-за того, что размер загружаемых данных не соответствует размеру файла : даже если вы публикуете максимальный размер, не превышенный размером файла , это может быть размер загруженных данных .
Смотрите эту страницу в руководстве по PHP.
; Maximum size of POST data that PHP will accept.
post_max_size = 8M
Еще одним источником проблем (для ОЧЕНЬ больших текстов) является кодировка UTF8. Вы можете оказаться с текстовой областью "шесть мегабайт", которая на самом деле состоит из 6 мега* символов*, и с международными кодовыми точками он может составлять, скажем, 8,2 мегабайта. Таким образом, вы получаете явно противоречивую ситуацию "шесть мегабайт данных превышают установленный лимит в 8 мегабайт".
Обновление
Вы сообщаете о двух явно противоречивых фактах:
PHP settings as follows (from phpinfo()):
post_max_size = 64M
И
PHP Warning: POST Content-Length of 12221448 bytes exceeds the limit of 8388608 bytes
Из PHPINFO ясно, что предел для POST составляет 64 М. Тем не менее, ошибка говорит, что предел составляет 8 м (по умолчанию). Поэтому мне кажется, что ваш код разговаривает с две разные реализации PHP (Два разных виртуальных хоста? Версия CGI и версия без CGI на одном хосте? Две разные машины?)
IIS будет повторно использовать процессы FastCGI. Вам нужно будет отключить все старые процессы, чтобы перезагрузить php.ini.
Отредактируйте модуль FastCGI и отредактируйте "отслеживать изменения в файле" и выберите файл php.ini. Это заставит дочерние процессы перезапускаться всякий раз, когда вы сохраняете изменение.
Вы можете изменить ограничения на -1, таким образом, у вас никогда не будет проблем с размером файлов. Вероятно, это не лучшее решение, так как вы в основном говорите: "если я этого не вижу, то его не существует", но поверьте, это действительно надежно и всегда будет работать.