Хмарне сховище
Модуль Хмарне сховище медіа тримає файли з /uploads — зображення
товарів, галереї, завантаження з редактора, згенеровані мініатюри — у
зовнішньому сховищі: Cloudflare R2, будь-якому S3-сумісному бакеті
(AWS S3, MinIO, Hetzner тощо) або на звичайному FTP-сервері. Він звільняє
диск на хостингу, дає віддавати картинки з CDN-домену й працює як шина файлів
між серверами, коли магазин живе на кількох.
Сторінка налаштувань — Модулі → Хмарне сховище медіа (S3/R2/FTP)
(/admin/cloudstorage). Таблиці модуля створює команда
php spark cloudstorage:install (один раз після встановлення з магазину;
самооновлення модуля виконує її саме).
Як це працює
Модуль не перехоплює завантаження. Файли лягають у /uploads як і раніше, а
модуль синхронізує їх опісля:
- Одразу після завантаження в адмінці — якщо запит адміністратора ніс файли, обмежена партія (до 30 свіжих файлів) одразу йде у сховище.
- Кожні 2 хвилини — задача Планувальника Хмарне сховище: синхронізація нових файлів підбирає все, чого перший хук не бачить: мініатюри, згенеровані на вітрині, CLI-імпорти, файли, записані другим сервером (до 300 файлів за прохід).
- Синхронізувати зараз на сторінці налаштувань запускає більший прохід руками (до 200 файлів); рядок результату каже, скільки відправлено.
Кожен синхронізований файл записується в індекс (шлях, розмір, час зміни). Файл, що змінився локально, перезаливається; якщо підключено модуль Cloudflare, його закешована адреса очищується, і нова версія видна одразу.
Віддача
Два режими віддачі, що перемикаються прапорцем Підміна URL на сторінках:
- Вимкнено — адреси лишаються рідними (
/uploads/...). Файл, який ще є локально, віддає вебсервер як звичайно; файл без локальної копії вбудований проксі модуля дістає зі сховища під тією самою адресою з 30-денними публічними кеш-заголовками (LiteSpeed теж його кешує). Окремий домен не потрібен. - Увімкнено — HTML сторінок переписується так, що посилання
/uploads/...ведуть на Публічний базовий URL (ваш CDN-домен), і браузер іде у сховище напряму. Посилання підміняється лише тоді, коли локальної копії немає і файл є в індексі — локальний файл завжди виграє, тому напівмігрований магазин рендериться правильно, а вимкнений модуль означає просто «все локально».
Звільнення диска
За замовчуванням локальні копії зберігаються. Поставте прапорець Видаляти
локальні копії — і після підтвердженої наявності файлу в сховищі локальна
копія видаляється; далі 2-хвилинна задача поступово вивантажує весь /uploads
сама. Якщо прапорець зняти, проксі відновлює локальну копію при першому запиті
файлу.
Перегенерація мініатюр товарів читає оригінали з диска. Перед нею на
вивантаженому магазині поверніть їх:
php spark cloudstorage:restore --prefix shop/products/origin.
Налаштування
Картка Бекенд:

| Поле | Значення |
|---|---|
| Драйвер | S3-сумісний (Cloudflare R2 / AWS S3 / MinIO) або FTP-сервер. |
| Endpoint, Bucket, Region, Access Key ID, Secret Key | Доступи S3. Region auto для R2. Порожній секрет — лишити збережений. |
| FTP хост / порт, Користувач, Пароль, Коренева тека | Доступи FTP і тека, куди класти файли. |
| Тека uploads (для CLI) | Абсолютний шлях до uploads/; задайте, якщо docroot сайту відрізняється від public/ застосунку — він потрібен spark-командам. |
Картка Віддача (CDN):
| Поле | Значення |
|---|---|
| Публічний базовий URL | Домен, з якого віддаються файли (для R2 — кастомний домен бакета, проксований Cloudflare). Шлях /uploads/... додається автоматично. |
| Підміна URL на сторінках | Два режими віддачі, описані вище. |
| Перевірити CDN | Проганяє весь ланцюжок — тестовий запис, анонімне читання зі сховища, базовий URL, DNS, наскрізний запит — і пропонує виправлення: Використати пряму адресу сховища, Відкрити публічне читання (uploads/*) для бакета, Підключити домен через Cloudflare для R2. |
Картка Синхронізація:
| Поле | Значення |
|---|---|
| Видаляти локальні копії | Режим вивантаження, див. вище. |
| Виключення (префікси) | Шляхи відносно uploads/, по одному на рядок (наприклад shop/products/origin, cmlTemp), які ніколи не синхронізуються й не вивантажуються. |
У панелі зверху — Перевірити з'єднання (звіряє, що доступи, бакет і endpoint збігаються), Синхронізувати зараз, Зберегти і кнопка Оновити модуль, яка зʼявляється, коли в магазині є новіша версія. Картка Стан показує кількість файлів у сховищі та скільки з них вивантажено.
Міграція і повернення (командний рядок)
| Команда | Що робить |
|---|---|
php spark cloudstorage:sync | Повна міграція /uploads у сховище. Опції: --prefix, --limit, --offload / --keep-local (перекривають налаштування на цей запуск), --dry-run. |
php spark cloudstorage:restore | Завантажує вивантажені файли назад у /uploads (--prefix, --limit). Файли повертаються байт у байт. |
php spark cloudstorage:quick | Обмежений прохід, який запускає планувальник (--limit, типово 300). |
Створіть бакет, заповніть S3-поля з регіоном auto, збережіть, натисніть
Перевірити з'єднання, потім Перевірити CDN — він скаже, чи читається
бакет і чи резолвиться публічний домен, і запропонує виправлення. Не вмикайте
Видаляти локальні копії, поки не завершиться перший повний
cloudstorage:sync і сторінки не виглядатимуть правильно.