# Медиа и миниатюры Раздел **Медиа** управляет файлами внутри `/uploads`: загрузкой, папками, переименованием, удалением, преобразованием изображений и автоматическими миниатюрами. Для просмотра требуется право `Медиа: просмотр`, для изменений — `Медиа: управление файлами`. SVG и другие активные веб-форматы в пользовательское хранилище не принимаются: при прямом открытии с домена сайта они способны выполнять встроенный код. Векторные иконки темы храните в её собственных assets, а для медиатеки экспортируйте изображение в PNG или WebP. Уже существующие SVG внутри `/uploads` отдаются только с защитными заголовками и как вложение. ## Какие файлы создаёт система AVE.cms различает оригинал и четыре вида производных файлов: | Вид | Расположение | Назначение | | --- | --- | --- | | Автоматическая миниатюра | `th/` рядом с оригиналом | Быстрый вывод изображения заданного размера на сайте и в панели. | | WebP-копия | Рядом с оригиналом, с тем же именем | Альтернативный формат для тега `` и других вариантов адаптивной загрузки. | | Копия из редактора | `_derivatives/` | Отдельный результат кадрирования, изменения размера или формата. | | Временный результат | `_derivatives/_preview/` | Живой предпросмотр редактора; старые временные файлы удаляются автоматически. | | Черновая загрузка документа | `.drafts/` | Закрытая от медиабраузера временная папка до успешного сохранения документа. | Каталоги `th` и `_derivatives` являются служебными и не показываются как обычные папки файлового браузера. Не добавляйте в них исходные материалы и не ссылайтесь на временные файлы из `_preview`. ## Файлы нового документа У нового документа ещё нет ID, поэтому медиа-поля не загружают файлы сразу в конечную папку. AVE.cms выдаёт редактору одноразовую сессию загрузки и временно помещает файлы в `/uploads/.drafts`. Сессия привязана к сотруднику, документу и конкретному полю. Папка не показывается в разделе **Медиа**. При успешном сохранении система получает ID документа, переносит файлы в папку поля, меняет пути в значении и только затем фиксирует документ. При ошибке валидации, БД или кода рубрики перенос откатывается. Неиспользованные черновики удаляются автоматически через 48 часов при последующих открытиях редактора. Конечный путь задаётся отдельно для каждого файлового поля в конструкторе рубрики: **Настройки типа → Папка файлов документа**. Например: ```text articles/doc_%id ``` Доступны подстановки: | Подстановка | Значение | | --- | --- | | `%id` | ID сохранённого документа. | | `%rubric_id` | ID рубрики. | | `%rubric_alias` | Алиас рубрики. | | `%field_id` | ID поля рубрики. | | `%field_alias` | Алиас поля. | | `%Y`, `%m`, `%d` | Год, месяц и день сохранения. | Путь можно писать с `/uploads` или без него. Пустая настройка получает безопасный стандарт `documents/%id/%field_alias`. Конструкция `..` и путь в служебную `.drafts` запрещены. Кнопка **Загрузить** создаёт новый файл и включает его в транзакционный перенос. Кнопка **Выбрать файл** ссылается на уже существующий объект медиатеки: такой файл остаётся в своей папке. При переносе JPG или PNG соседняя WebP-копия с тем же базовым именем переносится вместе с оригиналом; автоматические миниатюры будут построены заново по новому URL. ## Автоматическая генерация Миниатюра создаётся лениво — при первом HTTP-запросе к её URL. До первого открытия файла на диске может не быть. Например, для исходника: ```text /uploads/catalog/table.jpg ``` размер `c320x320` получает постоянный URL: ```text /uploads/catalog/th/table-c320x320.jpg ``` При одновременном первом запросе генерация защищена блокировкой: несколько посетителей не создают одну миниатюру параллельно. Готовый файл отдаётся с `ETag`, `Last-Modified` и браузерным кешем. Если исходник изменился позже миниатюры, она будет пересоздана при следующем обращении. Изменение версии генератора, качества JPEG или progressive-режима также инвалидирует старые автоматические миниатюры в затронутой папке. ## Режимы размеров Размер записывается как `<режим><ширина>x<высота>`, например `c320x320`. Ширина и высота должны быть от 1 до 4096 пикселей, а итоговая площадь — не более 4 000 000 пикселей. | Код | Поведение | Когда использовать | | --- | --- | --- | | `c` | Заполняет весь размер, сохраняя пропорции; лишнее обрезает по центру. | Квадратные карточки и аватары. | | `f` | Вписывает целое изображение в точный холст; свободное место заполняет белым. | Каталоги, где предмет нельзя обрезать. | | `t` | Пропорционально вписывает изображение в область в legacy-режиме без центрирования белыми полями. | Совместимость с существующими шаблонами. | | `r` | Растягивает изображение точно до указанной ширины и высоты. | Только когда допустимо изменение пропорций. | | `s` | Выполняет smart crop до точного размера. | Обложки с автоматическим кадрированием. | К режимам `c`, `r` и `s` можно добавить завершающую `r`, например `c480x320r`: генератор разрешит поменять ширину и высоту местами в зависимости от ориентации оригинала. Для новых шаблонов обычно достаточно `c` для карточек и `f` для изображений, которые нужно показать целиком. Режим `r` не следует использовать для фотографий товаров и людей. ## Использование в шаблонах В PHP-шаблоне поля используйте контекст поля, а не собирайте путь вручную: ```php first(); ?> <?= $template->escape(isset($image['description']) ? $image['description'] : '') ?> ``` В хранимых шаблонах документов, запросов и блоков доступен тег: ```text [tag:c320x320:/uploads/catalog/table.jpg] ``` Для кода модуля используйте штатный генератор URL: ```php use App\Frontend\Media\ThumbnailUrl; $url = ThumbnailUrl::make(array( 'link' => '/uploads/catalog/table.jpg', 'size' => 'c320x320', )); ``` Метод возвращает URL или `false`, если исходник недоступен, находится вне `/uploads`, размер некорректен либо отсутствует в белом списке. Не создавайте каталог `th` и имя файла самостоятельно: его имя задаётся системной настройкой и может измениться. Удалённый `http(s)`-исходник поддерживается только через защищённый downloader. Хост обязан разрешаться исключительно в публичные IP, порты ограничены `80/443`, каждый redirect проверяется повторно, а соединение привязывается к проверенному DNS-адресу. Ответ обрывается на 25 МБ; принимаются JPEG, PNG, GIF и WebP не более 12 000 пикселей по стороне и 50 Мп. Localhost, private/reserved сети, metadata endpoints, URL с логином/паролем и нестандартные порты возвращают placeholder. Не загружайте удалённые изображения самостоятельно из field-type или модуля. ## Ограничение доступных размеров Параметры находятся в **Настройки → Константы → Генерация миниатюр**: | Константа | Назначение | Значение по умолчанию | | --- | --- | --- | | `THUMBNAIL_DIR` | Имя служебной папки автоматических миниатюр. | `th` | | `THUMBNAIL_SIZES` | Обязательный белый список разрешённых размеров. | `t128x128,f128x128,c320x320,f480x360,t450x450` | | `JPG_QUALITY` | Качество JPEG-миниатюр. Фактический диапазон генератора — 40–100. | `90` | | `JPG_PROGRESSIVE` | Progressive JPEG. | Включено | | `THUMBNAIL_IPTC` | Добавление базовых IPTC-данных в JPEG. | Выключено | | `THUMBNAIL_CACHE_LIFETIME` | Срок браузерного кеша в секундах. | `1209600` | Генерация разрешена только для значений из `THUMBNAIL_SIZES`. Неизвестный пресет получает `404` до чтения исходника и запуска GD. Пустая или повреждённая runtime-настройка откатывается к минимальному системному набору `t128x128`, `f128x128`, `c320x320`, `f480x360`, `t450x450`; редактор константы не позволяет явно сохранить пустой или некорректный список. Откройте константу `THUMBNAIL_SIZES` и нажмите **Собрать**. Панель проверит серверные файлы темы, ядра и установленных модулей, затем текстовые значения текущих таблиц БД. Результат будет подставлен в поле, но применится только после нажатия **Сохранить**. Сборщик находит литеральные значения вроде `c320x320`. Размер, который код собирает динамически из отдельных переменных, нужно добавить вручную. Повторно запускайте сбор после установки модуля, переноса темы или изменения шаблонов в БД. Удалённые из списка размеры перестают генерироваться; уже созданные файлы можно убрать кнопкой **Очистить превью**. Историческая генерация через `?thumb=...` отключена. Запросы с этим параметром и адрес `/inc/thumb.php` отвечают `404`; используйте детерминированный URL, `ThumbnailUrl::make()` или `thumbnail()` контекста поля. После изменения `THUMBNAIL_DIR` старый каталог не переносится автоматически. Сначала обновите шаблоны и проверьте права записи, затем удалите прежние служебные папки вручную, если они больше не используются. ## Управление в файловом браузере На странице **Медиа** доступны два варианта очистки: - кнопка **Очистить превью** в шапке удаляет автоматические миниатюры текущей папки; - кнопка с той же иконкой у папки очищает превью непосредственно в выбранной папке. Оригиналы, соседние WebP-файлы и копии из `_derivatives` при такой очистке не удаляются. Нужные автоматические миниатюры появятся заново при следующем обращении. Очистка применяется только к выбранной папке, а не рекурсивно ко всему дереву `/uploads`. Для отдельного изображения откройте его карточку. Редактор позволяет выбрать кадр, размер, режим, формат и качество, увидеть живой результат и сохранить новую копию в `_derivatives`. Исходник при этом не перезаписывается. ## WebP Кнопка **В WebP** создаёт рядом с поддерживаемым растровым исходником файл с тем же базовым именем: ```text /uploads/catalog/table.jpg /uploads/catalog/table.webp ``` Кнопка доступна, только если библиотека GD умеет читать и записывать WebP. Существующая WebP-копия не перезаписывается. Для её замены удалите старую копию и выполните преобразование заново. Пример вывода с резервным JPG: ```php ``` Метод `webp()` только строит ожидаемый путь. Перед таким выводом убедитесь, что WebP-копия действительно создана, либо формируйте `` в типе поля после проверки файла. ## Переименование и удаление При переименовании JPG или PNG панель также переименовывает соседнюю WebP-копию с тем же базовым именем. Перед операцией проверяется конфликт нового имени. Автоматические миниатюры и копии редактора для прежнего имени очищаются. При удалении исходного JPG или PNG автоматически удаляются: - его миниатюры из `th`; - связанные результаты редактора из `_derivatives`; - соседняя WebP-копия с тем же базовым именем; - миниатюры этой WebP-копии. Удаление отдельного WebP не удаляет JPG или PNG: WebP может быть самостоятельным оригиналом. При удалении целой папки удаляется всё её содержимое, включая служебные производные. ## Если превью не создаётся Проверьте по порядку: 1. Исходник существует внутри `/uploads` и открывается напрямую. 2. Размер имеет формат вроде `c320x320`, не превышает 4096 пикселей по стороне и 4 000 000 пикселей по площади. 3. Размер присутствует в обязательном списке `THUMBNAIL_SIZES`. 4. Процесс PHP может создавать папки и файлы внутри каталога исходника. 5. GD поддерживает формат исходника и результата; для WebP нужна отдельная поддержка WebP в GD. 6. После замены изображения очистите превью его папки, если время изменения исходника было сохранено внешним инструментом и не стало новее миниатюры. Если исходник отсутствует, генератор пытается использовать `/uploads/images/noimage.png`. Добавьте этот файл в проект, если теме нужен единый placeholder.