Выгрузка медиа WordPress означает, что плагин копирует каждый файл, загруженный в медиабиблиотеку, в бакет S3 и переписывает URL картинок на страницах так, чтобы они указывали на бакет, а не на wp-content/uploads. Это сохраняет диск веб-сервера небольшим, позволяет нескольким веб-серверам делить одну медиабиблиотеку и переживает пересборку сервера. Но это же добавляет плагин, от которого вы зависите навсегда, меняет то, как работают backup, и - об этом большинство руководств молчит - работает, только если браузеры посетителей могут читать объекты, а это зависит от того, что разрешает ваше хранилище. Для собственного S3-совместимого endpoint чисто работают S3 Uploads от Human Made (настраивается в коде) и Advanced Media Offloader (настраивается в настройках, есть универсальный вариант для S3-совместимых сервисов); популярный WP Offload Media официально рассчитан на конкретных провайдеров, а до собственных endpoint дотягивается только через фильтры. В этой статье разобраны настройка, вопросы URL и доступа, перенос существующей библиотеки и честный ответ на вопрос, нужно ли вам всё это.
Что на самом деле меняет выгрузка#
Без выгрузки загруженный файл попадает в wp-content/uploads/2026/10/photo.jpg на веб-сервере, WordPress рядом генерирует уменьшенные копии (photo-300x200.jpg, photo-1024x683.jpg и так далее), а в содержимом записи оказывается URL самого сервера.
С плагином выгрузки загрузка всё равно сначала попадает на веб-сервер - WordPress нужен локальный файл, чтобы сгенерировать миниатюры и прочитать метаданные. Затем плагин копирует оригинал и все уменьшенные версии в бакет, запоминает, куда ушла каждая, и фильтрует все места, где WordPress формирует URL медиафайлов, чтобы страница указывала на хранилище. Некоторые плагины после этого удаляют локальные копии ради экономии диска, другие их сохраняют.
Отсюда два следствия. Картинки теперь посетители получают прямо с endpoint хранилища, значит, этот endpoint должен отвечать на анонимные запросы к этим объектам. А файлы теперь находятся вне веб-сервера, так что backup веб-сервера больше не содержит ваших медиафайлов.
Когда это того стоит, а когда нет#
Выгрузка решает конкретные проблемы. Если ни одной из них у вас нет, она лишь добавляет движущихся частей впустую.
Стоит, когда:
- Медиабиблиотека большая по сравнению с диском веб-тарифа - фотосайт или магазин с тысячами фото товаров, где загрузки занимают большую часть диска.
- Сайт обслуживает больше одного веб-сервера, и каждому нужны одни и те же файлы без синхронизации папок между ними.
- Веб-сервер одноразовый - вы пересобираете его из репозитория и не хотите держать на нём ничего, что нельзя воссоздать.
- Скачиваемые файлы большие - подкасты, видео, программы, - и вы хотите убрать их с канала и диска веб-сервера.
Не стоит, когда:
- Это обычный блог или сайт компании с несколькими гигабайтами картинок. Диска на тарифах веб-хостинга для этого хватает, а веб-сервер отдаёт статические файлы очень эффективно.
- Вы надеетесь, что сайт от этого сам по себе станет быстрее. Перенос картинок в бакет в той же площадке, что и веб-сервер, не сокращает расстояние до посетителей. Скорость дают заголовки кэширования, размеры и форматы изображений и CDN, если ваша аудитория далеко. Что действительно помогает, разобрано в статье скорость и кэширование WordPress.
- Вы полагаетесь на плагины, которые ждут локальных файлов, - некоторые редакторы изображений, генераторы миниатюр PDF, сканеры безопасности и плагины backup предполагают, что медиа лежит в
wp-content/uploads.
Есть и промежуточный путь, о котором забывают: оставьте медиа на месте и каждую ночь копируйте wp-content/uploads в бакет как backup. Никакого плагина, никаких изменений URL, а бакет всё равно спасёт вас при потере сервера. Подход с rclone из статьи backup игрового сервера в S3 точно так же работает для папки загрузок WordPress.
Вопрос публичного доступа#
Это нужно решить до того, как что-то устанавливать. Выгруженную картинку браузер посетителя загружает обычным GET без учётных данных. Чтобы это работало, хранилище должно отдавать эти объекты анонимно. В AWS это делается политикой бакета или ACL объектов со значением public-read. S3-совместимые сервисы различаются тем, какие из этих механизмов поддерживают, и далеко не каждый продукт хранения вообще предлагает публичные бакеты.
Хранилище S3 у RE:NODE, например, продаётся как приватное хранилище с ключом доступа и секретом, созданными для вашего сервера; публичные бакеты и политики бакетов не входят в то, что оно обещает. Поэтому проверьте, прежде чем строить на нём что-то. Загрузите тестовый объект так, как это будет делать ваш плагин, а затем запросите его без учётных данных:
$ aws s3 cp test.jpg s3://media/test.jpg --acl public-read --profile store$ curl -I https://s3.example.com/media/test.jpgОтвет 200 с Content-Type: image/jpeg означает, что анонимное чтение работает, а значит, заработает и публичная схема выгрузки. Ответ 403 AccessDenied означает, что объекты приватные, и у вас три честных варианта:
- Подписанные URL. Некоторые плагины умеют отдавать медиа через presigned URL с ограниченным сроком действия. S3 Uploads делает так для вложений, помеченных как приватные. Это работает, но при каждом рендере страницы получаются другие URL картинок, что убивает кэширование страниц и браузерное кэширование: годится для закрытой зоны для участников, плохо подходит для публичного сайта. Механика и её ограничения объясняются в статье presigned URL.
- Отдавать медиа через сервер, который вы контролируете, который держит ключи и забирает файлы из бакета, - reverse proxy или небольшое приложение, подписывающее запросы. Это настоящая работа и лишний переход; она имеет смысл главным образом тогда, когда контроль доступа вам нужен в любом случае.
- Использовать бакет как копию для backup, а не для раздачи. Держите медиа на веб-сервере и каждую ночь синхронизируйте их в бакет. Просто, надёжно и без переписывания URL.
Для большинства сайтов на WordPress с приватным хранилищем правильный вариант - третий.
Плагины и их поддержка собственного endpoint#
В любом обсуждении всплывают три плагина. Различаются они в основном тем, как работают с endpoint не от AWS.
| Плагин | Где настраивается | Собственный S3 endpoint | Path-style | Существующие медиа |
|---|---|---|---|---|
| S3 Uploads (Human Made) | wp-config.php и фильтр | Да, через s3_uploads_s3_client_params | Да, use_path_style_endpoint | Команда WP-CLI |
| Advanced Media Offloader | Константы или страница настроек | Да, универсальный вариант для S3-совместимых | Да, константа | Массовый инструмент и WP-CLI |
| WP Offload Media (Lite/Pro) | Страница настроек или AS3CF_SETTINGS | Официально нет; через фильтры | Через те же фильтры | Массовый инструмент в Pro |
S3 Uploads - плагин для разработчиков: никакого экрана настроек, всё в коде, устанавливается с GitHub или через Composer, а не из каталога плагинов. Он прозрачнее всех в том, что делает, поэтому его проще всего отлаживать. Advanced Media Offloader есть в каталоге плагинов WordPress, у него есть универсальный вариант провайдера для S3-совместимых сервисов с endpoint, доменом и переключателем path-style, и он умеет удалять локальные копии после загрузки («Full Cloud Migration») или оставлять их как запасной вариант. WP Offload Media - самое известное имя; его Lite-версия официально поддерживает Amazon S3, DigitalOcean Spaces и Google Cloud Storage, а позиция самого разработчика насчёт других S3-совместимых сервисов такая: с фильтрами они, вероятно, работают, но не протестированы. Если вы уже пользуетесь им с AWS - всё в порядке; для собственного endpoint любой из двух других доставит меньше хлопот.
Настройка S3 Uploads с собственным endpoint#
Установите плагин по его README (Composer: composer require humanmade/s3-uploads, или скачайте релиз в wp-content/plugins), затем добавьте константы в wp-config.php выше строки «That's all, stop editing»:
define( 'S3_UPLOADS_BUCKET', 'media/wp' ); // bucket, optional prefixdefine( 'S3_UPLOADS_REGION', 'us-east-1' ); // any value the store acceptsdefine( 'S3_UPLOADS_KEY', getenv( 'S3_KEY' ) );define( 'S3_UPLOADS_SECRET', getenv( 'S3_SECRET' ) );define( 'S3_UPLOADS_BUCKET_URL', 'https://s3.example.com/media/wp' );define( 'S3_UPLOADS_HTTP_CACHE_CONTROL', 'public, max-age=31536000' );Endpoint и переключатель path-style задаются в небольшом must-use плагине, потому что это опции клиента SDK, а не настройки плагина:
<?phpadd_filter( 's3_uploads_s3_client_params', function ( $params ) { $params['endpoint'] = 'https://s3.example.com'; $params['use_path_style_endpoint'] = true; $params['request_checksum_calculation'] = 'when_required'; $params['response_checksum_validation'] = 'when_required'; return $params;} );Две строки про контрольные суммы нужны для свежих версий AWS SDK для PHP (3.337 и новее), которые добавляют контрольные суммы целостности, отвергаемые некоторыми S3-совместимыми серверами; README самого плагина рекомендует их для сторонних endpoint. S3_UPLOADS_BUCKET_URL задаёт базовый URL, который пишется в страницы, - при path-style это endpoint плюс бакет и префикс. По возможности держите ключ и секрет вне самого файла, как это делают вызовы getenv() выше; почему - объясняет статья переменные окружения и секреты.
S3 Uploads по умолчанию ставит объектам public-read (S3_UPLOADS_OBJECT_ACL). В хранилище, которое не учитывает ACL, эта настройка ни на что не влияет, и вы возвращаетесь к проверке публичного доступа, описанной выше.
Прежде чем полагаться на настройку, проверьте её через WP-CLI: wp s3-uploads verify проверяет, что плагин может записывать в бакет и удалять из него.
Перенос существующей библиотеки#
Новые загрузки выгружаются автоматически. Всё, что загружено до включения плагина, - нет, и эти записи по-прежнему указывают на wp-content/uploads. Перенос состоит из двух половин: скопировать файлы и поменять URL.
- Сначала сделайте backup. База данных и
wp-content/uploads. Смена URL - это поиск с заменой по всему вашему содержимому. - Скопируйте файлы. С S3 Uploads:
wp s3-uploads upload-directory wp-content/uploads uploads. С Advanced Media Offloader: его массовый инструмент илиwp advmo offloadдля больших библиотек. - Перепишите URL в содержимом. Плагины выгрузки фильтруют URL, которые генерирует WordPress, но URL, вставленные в текст записей, - это просто текст. С ними справится поиск с заменой в WP-CLI:
wp search-replace 'https://example.com/wp-content/uploads' 'https://s3.example.com/media/wp/uploads' --all-tables --dry-run, а затем то же самое без--dry-run. Убедитесь, что целевой путь совпадает с тем, куда ваш плагин действительно кладёт файлы. - Проверьте страницы. Откройте несколько старых записей и галерею товаров и поищите на вкладке сети в браузере картинки, которые всё ещё грузятся по старому пути.
- Только после этого удаляйте локальные копии, если хотите вернуть место на диске. Держите их, пока не будете уверены.
Откат переноса - тот же процесс в обратную сторону, и это сильнейший аргумент за сохранение локальных копий: сайт, у которого единственная копия медиа лежит в бакете, привязан к этому плагину и этому хранилищу.
Backup после выгрузки#
Это изменение люди обнаруживают во время восстановления. Backup вашего веб-сервера - backup панели, плагин backup, tar сайта - теперь содержат базу данных и код, но не медиа. Бакет - единственное место, где живёт любой файл, локальная копия которого была удалена.
На RE:NODE хранилище S3 держит одну копию на NVMe в одной площадке, без репликации, а у тарифов хранилища нет собственных слотов backup в панели. Для копии, с которой идёт раздача, это нормально - при условии, что вторую копию держит что-то ещё. Два способа её сохранить:
- Сохраняйте локальные копии на веб-сервере, чтобы существующие backup веб-сервера по-прежнему включали медиа.
- Синхронизируйте бакет в другое место, например
rclone sync store:media/wp /backups/wp-mediaна машине, которую вы контролируете, или ко второму провайдеру, по расписанию.
Также делайте backup настроек плагина и - для плагинов, которые отслеживают выгруженные элементы в собственной таблице базы данных, - самой базы: если восстановить файлы без этой таблицы, плагин не будет знать, где что лежит. Статью перенос WordPress к новому хостингу стоит читать с учётом этого: у сайта с выгрузкой на одну переносимую часть больше.
Частые проблемы#
Картинки отдают 403 после выгрузки. Объекты приватные, и хранилище не отдаёт их анонимно. См. раздел о публичном доступе: либо используйте подписанные URL, либо держите медиа локально.
Новые загрузки падают с ошибкой подписи или контрольной суммы. Это более новые контрольные суммы SDK по умолчанию; добавьте две опции when_required.
Часть картинок всё ещё грузится из `wp-content/uploads`. Жёстко прописанные URL в содержимом или в данных конструктора страниц. Сделайте поиск с заменой, а для конструкторов страниц, которые хранят сериализованные данные, используйте wp search-replace, который правильно обрабатывает сериализацию, - обычный SQL REPLACE() её ломает.
В бакете не хватает миниатюр. Размеры, сгенерированные темой или плагином после исходной загрузки, выгружаются не всегда. Перегенерируйте миниатюры, а затем повторно запустите выгрузку плагином для этих элементов.
Сайт стал медленнее. Запросы картинок теперь идут на второе имя хоста, со своим соединением и TLS-рукопожатием. Долгие заголовки Cache-Control помогают при повторных визитах; значения разобраны в статье заголовки HTTP-кэширования. Для далёких посетителей настоящее решение - CDN перед именем хоста с медиа.
FAQ#
Ускоряет ли выгрузка медиа WordPress?
Сама по себе - нет. Веб-сервер и так эффективно отдаёт статические картинки, а бакет в той же площадке находится на том же расстоянии от посетителей. Выгрузка экономит диск и помогает схемам с несколькими серверами; скорость дают кэширование, оптимизация изображений и CDN.
Какой плагин работает с S3-совместимым endpoint?
S3 Uploads - через фильтр, задающий endpoint и path-style, и Advanced Media Offloader - через свой универсальный вариант для S3-совместимых сервисов. WP Offload Media можно заставить работать с помощью фильтров, но собственные endpoint он официально не поддерживает.
Обязательно ли удалять локальные копии?
Нет, и сохранять их безопаснее. Локальные копии сохраняют полноту backup веб-сервера и позволяют отключить плагин, не потеряв картинки. Удаляйте их, только если вы затеяли выгрузку именно ради места на диске.
Можно ли выгружать только часть файлов?
Большинство плагинов выгружают всё содержимое медиабиблиотеки. Если в бакете вам нужны только большие файлы для скачивания, загрузите их напрямую через клиент S3 и поставьте на них ссылки, а библиотеку не трогайте.
Что будет, если отключить плагин?
URL вернутся к wp-content/uploads. Если локальные файлы на месте, сайт продолжит работать; если они были удалены, картинки сломаются, пока вы не скопируете их обратно из бакета и не перепишете URL, изменённые в содержимом.




Комментарии
Полностью анонимно: без аккаунта, без почты, без cookie. Мы храним имя, которое вы ввели, текст и время - больше ничего. Количество ссылок ограничено, разметка не отображается.