Перейти к содержимому
Ошибки и сбои

Ошибка HTTP при загрузке изображения в WordPress: дерево решений, которое реально находит причину

Один взгляд на ответ сервера отделяет настоящую причину ошибки HTTP при загрузке изображения в WordPress: файрвол, память PHP, post_max_size или Imagick.

Опубликовано

«Ошибка HTTP» — это не причина. Это признание загрузчика медиафайлов: файл на сервер он отправил, а в ответ получил то, что не смог распознать как успех. И как минимум шесть никак не связанных между собой сбоев дают ровно эту формулировку. Именно поэтому люди тратят полдня на увеличение upload_max_filesize на сайте, где на самом деле мешает правило файрвола.

Быстрее всего выбраться так: одно наблюдение делит шесть причин на две группы, дальше по одной проверке на ветку.

Сначала: посмотрите на настоящий ответ

Откройте инструменты разработчика в браузере, перейдите на вкладку «Сеть» и загрузите файл ещё раз. Найдите запрос к async-upload.php. То, что вернулось, и есть ваш диагноз.

Что вы видитеЧто это значитКуда идти
403 или 406, тело в HTMLЗапрос отклонил файрвол или mod_securityВетка A
500, пустой или обрезанный ответPHP упал или исчерпал память на полпутиВетка B
413Тело запроса превысило серверный лимитВетка C
200, но в теле не чистый JSONПлагин или тема вывели что-то до ответаВетка D
Запрос не завершается / таймаутЛимит времени выполнения, обычно на крупных файлахВетка B

Один этот взгляд отсекает большую часть советов из интернета. Если до инструментов разработчика не добраться, сначала включите логирование в wp-config.php:

define( 'WP_DEBUG', true );
define( 'WP_DEBUG_LOG', true );
define( 'WP_DEBUG_DISPLAY', false );

Повторите загрузку и прочитайте wp-content/debug.log. Строка с фатальной ошибкой прямо называет ветку. Если строка выглядит непонятно, вставьте её в расшифровщик логов ошибок — он сопоставляет типовые фатальные сигнатуры с тем, что сломалось на самом деле.

Ветка A — файрвол или правило mod_security

Код 403 с HTML-страницей в теле означает, что запрос до WordPress вообще не дошёл. Что-то перед ним — mod_security, Cloudflare, Wordfence, Sucuri или собственный набор правил хостинга — сочло POST-запрос подозрительным.

Проверка: временно отключите плагин безопасности и загрузите файл снова. Если ничего не изменилось, правило живёт на уровне сервера, и нужно, чтобы хостинг посмотрел журнал аудита mod_security по времени неудачной загрузки. Там можно добавить конкретный ID правила в белый список.

И честно о советах, которые вам здесь попадутся. Сниппеты, предлагающие вставить это в .htaccess:

SecFilterEngine Off
SecFilterScanPOST Off

рассчитаны на mod_security 1.x, который практически вымер. На современном сервере эти директивы либо не делают ничего, либо выдают 500 и делают только хуже. Актуальный mod_security использует SecRuleEngine, и большинство управляемых хостингов всё равно запрещают переопределять его на уровне каталога. Спросите хостинг, а не вставляйте вслепую.

Ветка B — лимиты памяти или времени выполнения PHP

Самая частая ветка, и у неё самый явный признак: сбой плавающий. Тот же файл загружается с третьей попытки, или фотография на 2 МБ не проходит, а PDF на 6 МБ проскакивает без проблем. Жёсткие настроенные лимиты срабатывают одинаково всегда. Нехватка памяти — нет, потому что доступный объём зависит от того, чем ещё занят сервер.

Почему это касается именно изображений: WordPress не просто сохраняет файл, он распаковывает его в сырые пиксели, чтобы сгенерировать все промежуточные размеры — medium_large, всё, что зарегистрировано через add_image_size, woocommerce_thumbnail, если у вас магазин, плюс копию -scaled, если изображение превышает big_image_size_threshold. JPEG на 12 мегапикселей занимает несколько мегабайт на диске и около 48 МБ в памяти — ещё до буфера под изменение размера. Лимит в 128 МБ уходит мгновенно.

Поднимите его в wp-config.php, выше строки «stop editing»:

define( 'WP_MEMORY_LIMIT', '256M' );
define( 'WP_MAX_MEMORY_LIMIT', '512M' );

Реальная цена вопроса: WP_MEMORY_LIMIT не может превысить то, что разрешает сам PHP. Если хостинг ограничивает memory_limit значением 128M, эта константа декоративна. Смотрите настоящее значение в «Инструменты → Здоровье сайта → Информация → Сервер», а не в том, что вы написали. Если потолок задаёт сам PHP, поднять его может только хостинг.

Ветка C — размер файла и лимиты запроса

Посмотрите реальные цифры в «Инструменты → Здоровье сайта → Информация → Обработка медиафайлов». Значение имеют две настройки, а меняют обычно только одну:

  • upload_max_filesize — предел для одного файла.
  • post_max_size — предел для всего тела запроса.

Если весь POST-запрос превышает post_max_size, PHP отбрасывает его до того, как WordPress выполнит хоть строчку кода. Возвращать нечего, загрузчик получает неразбираемый ответ и пишет «Ошибка HTTP». post_max_size всегда должен быть заметно больше upload_max_filesize.

Полезная оговорка: когда файл превышает только upload_max_filesize, загрузчик обычно ловит это ещё в браузере и сообщает, что файл больше максимально допустимого размера, — формулировка гораздо понятнее. Так что голая «Ошибка HTTP» чаще указывает на post_max_size или на ветку B, чем на тот параметр, который все поднимают первым.

Где их менять, зависит от вашего стека. На Apache с mod_php работает .htaccess:

php_value upload_max_filesize 64M
php_value post_max_size 128M

На PHP-FPM, LiteSpeed или NGINX — а это большинство современных хостингов — эти строки не делают ничего и могут вызвать 500. Используйте панель настроек PHP у хостера или файл .user.ini. NGINX вдобавок применяет собственный client_max_body_size, поднять который может только хостинг.

Ветка D — библиотека обработки изображений (Imagick или GD)

WordPress предпочитает ImageMagick, когда расширение PHP установлено, и откатывается на GD. На виртуальных хостингах ImageMagick часто и есть проблема: его файл политик ограничивает память, диск и площадь изображения на операцию, и когда изменение размера упирается в один из лимитов, процесс умирает без внятного сообщения. Обычно это видно на крупных изображениях, тогда как мелкие проходят, — выглядит как ветка B, но ею не является.

Чтобы проверить гипотезу, принудительно включите GD:

add_filter( 'wp_image_editors', function ( $editors ) {
    return array( 'WP_Image_Editor_GD' );
} );

Добавьте это в functions.php или в небольшой mu-плагин, повторите загрузку и уберите, если ничего не изменилось.

Честный компромисс: GD не безусловно лучше. Он держит полный несжатый растр в памяти PHP, поэтому на очень больших файлах может упереться в memory_limit там, где ImageMagick — работающий частично за пределами выделенной PHP памяти — справился бы. Переключение может обменять один сбой на другой. Считайте это в первую очередь диагностикой и только во вторую — решением.

Ветка E — права на каталог загрузок

На управляемом хостинге встречается редко, зато обычное дело сразу после переноса или ручного перемещения сервера. Если wp-content/uploads недоступен для записи пользователю веб-сервера, либо у только что созданной подпапки года/месяца оказался не тот владелец, запись не проходит.

ls -ld wp-content/uploads
ls -ld wp-content/uploads/2026/07

У каталогов обычно должны быть права 755 и владелец — тот пользователь, от имени которого работает PHP. Не ставьте 777 только потому, что так посоветовали на форуме: это лечит симптом ценой того, что папка становится доступна на запись любой учётной записи на сервере, а на виртуальном хостинге это настоящая уязвимость.

Ветка F — имя файла

Самая дешёвая проверка в списке, поэтому делайте её рано, хотя вероятность и наименьшая. Переименуйте файл в обычные строчные латинские буквы, цифры и дефисы — без диакритики, апострофов, амперсандов, # и нелатинских символов — и загрузите снова. Спецсимволы иногда задевают правило безопасности или ломаются на файловой системе с несовпадающей кодировкой. Десять секунд, чтобы исключить вариант.

Чего делать не стоит

Не начинайте с отключения всех плагинов. Это разрушительно и проверяет только ветки A и D. Сетевой ответ расскажет больше за пять секунд.

Не добавляйте случайную строку с обработчиком в .htaccess. Гуляющие по сети сниппеты с директивами SetHandler или AddHandler рассчитаны на конкретную настройку PHP у конкретного хостера. На чужом стеке они кладут весь сайт с ошибкой 500.

Не считайте «со второго раза получилось» решением. Успех через раз — фирменный признак ветки B, и всё вернётся, как только сервер загрузится или кто-то зальёт файл побольше.

Всё ещё не получается?

Если ответ — чистый 200 с корректным JSON, а загрузка всё равно не проходит, поломка находится уже после того, как файл принят: обычно это плагин, подключённый к цепочке обработки вложений и выдающий фатальную ошибку, либо плагин-оптимизатор, который шлёт собственный запрос во внешний сервис и не дожидается ответа. Включите WP_DEBUG_LOG, повторите загрузку и прогоните полученную фатальную ошибку через расшифровщик логов ошибок, чтобы понять, какой файл и какой хук за это отвечают.

FAQ

Вопросы

Что означает «Ошибка HTTP» при загрузке изображений в WordPress?

Это значит, что загрузчик в браузере отправил файл на сервер и получил в ответ нечто, что не смог разобрать как корректный успешный ответ. Сообщение описывает симптом, а не причину. Упавший процесс PHP, блокировка файрволом, ответ 403 и пустой ответ дают одни и те же два слова.

Почему одно и то же изображение то загружается, то нет?

Плавающие сбои почти всегда указывают на нехватку памяти или процессорного времени, а не на настроенный лимит. Для изменения размера большой фотографии нужен всплеск памяти, а на виртуальном хостинге доступный объём меняется вместе с нагрузкой на сервер. Жёсткий лимит вроде post_max_size срабатывает совершенно одинаково каждый раз.

Помогает ли переключение WordPress с Imagick на GD?

Иногда, и только в одной конкретной ветке. ImageMagick на виртуальных хостингах часто ограничен файлом политик или низкими лимитами ресурсов и падает там, где GD справляется. Но GD расходует больше памяти на очень крупные файлы, поэтому переключение может усугубить сбои, вызванные нехваткой памяти.

Как понять, что загрузку блокирует файрвол хостинга?

Откройте панель сетевых запросов в браузере, загрузите файл и посмотрите код ответа для async-upload.php. Код 403 или 406 с HTML-телом означает, что запрос отклонил веб-файрвол или правило mod_security. Код 500 или пустой ответ указывают на падение PHP.

Исправит ли ошибку HTTP увеличение upload_max_filesize?

Только если файл действительно превышает ваши лимиты, причём post_max_size обычно важнее. Если всё тело запроса больше post_max_size, PHP отбрасывает его до запуска WordPress, и загрузчик не получает вообще ничего. Поднять один параметр без другого — значит оставить сбой ровно там, где он был.

Может ли имя файла вызвать ошибку HTTP в WordPress?

Да, хотя это самая редкая ветка. Диакритика, апострофы, амперсанды и нелатинские алфавиты способны задеть правило безопасности или сломать путь при несовпадении кодировок файловой системы. Переименование в обычные строчные латинские буквы, цифры и дефисы ничего не стоит и снимает вопрос секунд за десять.