Медиафайлы¶
Эндпоинты для управления медиафайлами, прикреплёнными к страницам, и медиафайлами уровня сайта, их метаданными в .meta.yaml, ручным порядком папок медиафайлов сайта и файлами, сохранёнными полями схем с типом «файл». Для чтения нужно api.media.read, а для любых изменений — api.media.write. Медиафайлы страницы также подчиняются собственным правилам доступа страницы, поэтому страница, которая запрещает вам чтение или обновление, возвращает 403. Миниатюры публичны.
Список медиафайлов страницы¶
GET /pages/{route}/media
Выводит все медиафайлы страницы с необязательной фильтрацией и сортировкой по метаданным.
Параметры
| Имя | Тип | Обязательный | Описание |
|---|---|---|---|
route |
string | Да | Маршрут страницы |
filter |
string | Нет | Фильтр по метаданным в виде field:operator:value (или field:value). Можно повторять через filter[]=. Операторы: == != > >= < <= in contains. |
sort |
string | Нет | Поле метаданных (или встроенное filename/size/modified), по которому сортировать |
order |
string | Нет | Направление сортировки: asc (по умолчанию) или desc |
Ответ
{"data": [{"filename": "photo.jpg", "url": "/user/pages/01.blog/photo.jpg", "type": "image/jpeg", "size": 245000, "alt": "Sunset over the bay", "dimensions": {"width": 1920, "height": 1080}, "thumbnail_url": "/api/v1/thumbnails/3f2a9c1e4b5d6a7f8e9d0c1b2a394857.jpg", "modified": "2026-09-01T10:15:00+00:00"}]}
Коды ответов
| Код | Описание |
|---|---|
200 |
Успех |
401 |
Не авторизован |
403 |
Нет разрешения api.media.read или правила самой страницы запрещают чтение |
404 |
Страница не найдена |
422 |
Неверный параметр filter/sort |
Фильтрация и сортировка по метаданным¶
Если у ваших медиафайлов есть метаданные в сопутствующих файлах .meta.yaml, список можно фильтровать и сортировать по этим значениям, а не загружать весь набор. Это повторяет методы запросов коллекций Twig, но привязано к схеме метаданных, настроенной в разделе Плагины → API → Метаданные медиафайлов (plugins.api.media_metadata.fields).
Фильтр¶
Каждое условие filter имеет вид field:operator:value. Повторяйте его через filter[]=, чтобы применить несколько условий (они объединяются по И):
Доступные операторы: ==, !=, >, >=, <, <=, in и contains. Оператор можно опустить (filter=copyright:Jane Doe) — тогда он выводится из типа поля: contains для поля tags, == в остальных случаях. Для оператора in укажите набор через запятую: filter=rating:in:4,5.
Сортировка¶
sort принимает любое настроенное поле метаданных, а также встроенные ключи filename, size и modified. order — это asc (по умолчанию) или desc; медиафайлы без поля сортировки всегда идут последними. (dir принимается как псевдоним order.)
Правила и ограничения¶
- Привязка к схеме. Фильтровать и сортировать можно только по полям, определённым в
media_metadata.fields; неизвестные поля игнорируются. Полеtagsпринимает толькоin/contains. - Валидация. Неизвестный оператор, некорректное условие, неверное поле
sortили больше 10 условийfilterвозвращают422. Фильтрация использует существующее разрешениеapi.media.readи не раскрывает значений метаданных, которые вызывающая сторона и так не могла прочитать. - Ограничение. Не более 10 условий
filterна запрос.
Загрузка медиафайлов страницы¶
POST /pages/{route}/media
Загружает файл(ы) на страницу через данные multipart-формы.
Параметры
| Имя | Тип | Обязательный | Описание |
|---|---|---|---|
route |
string | Да | Маршрут страницы |
file |
file | Да | Загружаемый файл (multipart/form-data). Подходит любое имя поля, включая имена вложенных массивов, например files[]; в одном запросе можно отправить несколько файлов. |
random_name |
boolean | Нет | Заменить имя файла случайным, сохранив расширение (по умолчанию: false) |
avoid_overwriting |
boolean | Нет | Добавить префикс с отметкой времени вместо замены существующего файла с тем же именем (по умолчанию: false) |
accept |
string | Нет | Список разрешённых расширений через запятую (.pdf, *.jpg) или шаблонов MIME (image/*) |
filesize |
number | Нет | Максимальный размер для поля в МБ. Может только уменьшить предел 64 МБ. |
Ответ
{"data": [{"filename": "photo.jpg", "url": "/user/pages/01.blog/photo.jpg", "type": "image/jpeg", "size": 245000, "dimensions": {"width": 1920, "height": 1080}, "thumbnail_url": "/api/v1/thumbnails/3f2a9c1e4b5d6a7f8e9d0c1b2a394857.jpg", "modified": "2026-09-01T10:15:00+00:00"}]}
Коды ответов
| Код | Описание |
|---|---|
201 |
Файл загружен |
401 |
Не авторизован |
403 |
Нет разрешения api.media.write или правила самой страницы запрещают обновление |
404 |
Страница не найдена |
422 |
Ошибка валидации (нет файла, неверное имя или тип файла, либо файл слишком большой) |
Отправляйте файл запросом multipart/form-data, а не JSON. Заголовок Content-Type должен иметь значение multipart/form-data.
Ответ перечисляет все медиафайлы страницы после загрузки, а не только новые файлы, а заголовок Location указывает на коллекцию медиафайлов страницы. Размер каждого файла ограничен 64 МБ. У файла должно быть расширение, и ни одна разделённая точками часть его имени не должна входить в security.uploads_dangerous_extensions (поэтому shell.php.jpg отклоняется). Содержимое SVG санируется при поступлении.
Необязательные поля формы random_name, avoid_overwriting, accept и filesize применяют настройки загрузки поля схемы с типом «файл» поверх этих проверок.
Удаление медиафайла страницы¶
DELETE /pages/{route}/media/{filename}
Удаляет медиафайл со страницы.
Параметры
| Имя | Тип | Обязательный | Описание |
|---|---|---|---|
route |
string | Да | Маршрут страницы |
filename |
string | Да | Имя удаляемого медиафайла |
Коды ответов
| Код | Описание |
|---|---|
204 |
Файл удалён |
401 |
Не авторизован |
403 |
Нет разрешения api.media.write или правила самой страницы запрещают обновление |
404 |
Страница или файл не найдены |
422 |
Неверное имя файла (начинается с точки или содержит ..) |
Удаляет файл и его сопутствующий файл .meta.yaml, если он есть. Варианты файла для retina (name@2x.jpg, name@3x.jpg и т. д.) и их сопутствующие файлы тоже удаляются, поэтому изображение, сохранённое только как вариант retina, всё равно можно удалить по базовому имени.
Список медиафайлов сайта¶
GET /media
Выводит медиафайлы и папки уровня сайта с постраничной разбивкой, просмотром подпапок, поиском, фильтрацией по типу, а также фильтрацией и сортировкой по метаданным.
Параметры
| Имя | Тип | Обязательный | Описание |
|---|---|---|---|
page |
integer | Нет | Номер страницы для постраничной разбивки (по умолчанию: 1) |
per_page |
integer | Нет | Число результатов на странице (по умолчанию: 20, максимум: 1000, оба значения настраиваются) |
path |
string | Нет | Путь подпапки относительно корневой директории медиафайлов |
search |
string | Нет | Рекурсивный поиск по имени файла без учёта регистра во всех подпапках. Нельзя сочетать с filter или sort. |
type |
string | Нет | Фильтр по типу медиафайла: image, video, audio или document (всё, что не image, video или audio) |
filter |
string | Нет | Фильтр по метаданным в виде field:operator:value (или field:value). Можно повторять через filter[]=, до 10 условий. Те же правила, что и для медиафайлов страницы. |
sort |
string | Нет | Поле метаданных (или встроенное filename/size/modified), по которому сортировать. Переопределяет ручной порядок папки. |
order |
string | Нет | Направление сортировки: asc (по умолчанию) или desc |
Ответ
{"data": [{"filename": "hero.jpg", "path": "blog", "url": "/user/media/blog/hero.jpg", "type": "image/jpeg", "size": 184320, "dimensions": {"width": 1600, "height": 900}, "thumbnail_url": "/api/v1/thumbnails/3f2a9c1e4b5d6a7f8e9d0c1b2a394857.jpg", "modified": "2026-09-01T10:15:00+00:00"}], "meta": {"pagination": {"page": 1, "per_page": 20, "total": 1, "total_pages": 1}, "path": "blog", "folders": [{"name": "2026", "path": "blog/2026", "children_count": 0, "file_count": 4}], "ordered": false}, "links": {"self": "/api/v1/media?page=1&per_page=20"}}
Коды ответов
| Код | Описание |
|---|---|
200 |
Успех |
401 |
Не авторизован |
403 |
Нет разрешения api.media.read |
422 |
Неверный путь, search вместе с filter или sort, либо неверный параметр filter/sort |
Возвращает медиафайлы и папки из директории user/media. Поддерживает просмотр подпапок через параметр path, рекурсивный поиск через search, фильтрацию по типу файла через type и фильтрацию с сортировкой по метаданным .meta.yaml через filter, sort и order (синтаксис фильтра см. в разделе Список медиафайлов страницы). Ответ содержит массив folders в объекте meta со списком непосредственных подпапок текущего пути, а meta.ordered сообщает, есть ли у папки сохранённый ручной порядок.
Файлы идут в сохранённом ручном порядке папки (см. Задание порядка медиафайлов), если он есть, иначе — в естественном порядке имён. Сопутствующие файлы .meta.yaml и файл порядка media_order.yaml никогда не попадают в список — ни при просмотре папки, ни в результатах поиска.
Для несуществующей папки возвращается пустой список, при этом meta.pagination повторяет запрошенные page и per_page, а meta.ordered отсутствует. В режиме поиска meta.path пуст, meta.folders пуст, meta.search содержит поисковый запрос, а meta.ordered отсутствует.
Загрузка медиафайлов сайта¶
POST /media
Загружает файлы в директорию медиафайлов уровня сайта.
Параметры
| Имя | Тип | Обязательный | Описание |
|---|---|---|---|
path |
string | Нет | Параметр запроса: путь подпапки для загрузки (создаётся автоматически, если не существует) |
file |
file | Да | Загружаемый файл (multipart/form-data). Подходит любое имя поля, включая имена вложенных массивов, например files[]; в одном запросе можно отправить несколько файлов. |
random_name |
boolean | Нет | Заменить имя файла случайным, сохранив расширение (по умолчанию: false) |
avoid_overwriting |
boolean | Нет | Добавить префикс с отметкой времени вместо замены существующего файла с тем же именем (по умолчанию: false) |
accept |
string | Нет | Список разрешённых расширений через запятую (.pdf, *.jpg) или шаблонов MIME (image/*) |
filesize |
number | Нет | Максимальный размер для поля в МБ. Может только уменьшить предел 64 МБ. |
Ответ
{"data": [{"filename": "hero.jpg", "path": "blog", "url": "/user/media/blog/hero.jpg", "type": "image/jpeg", "size": 184320, "dimensions": {"width": 1600, "height": 900}, "thumbnail_url": "/api/v1/thumbnails/3f2a9c1e4b5d6a7f8e9d0c1b2a394857.jpg", "modified": "2026-09-01T10:15:00+00:00"}]}
Коды ответов
| Код | Описание |
|---|---|
201 |
Файлы успешно загружены |
401 |
Не авторизован |
403 |
Нет разрешения api.media.write |
422 |
Ошибка валидации (нет файла, неверный путь, имя или тип файла, либо файл слишком большой) |
Загружает один или несколько файлов в директорию user/media. Используйте параметр запроса path, чтобы загрузить в подпапку. Тело запроса должно быть в формате multipart/form-data с полем file. Максимальный размер загрузки на файл — 64 МБ.
Ответ перечисляет только файлы, сохранённые этим запросом. У файла должно быть расширение, и ни одна разделённая точками часть его имени не должна входить в security.uploads_dangerous_extensions. Содержимое SVG санируется при поступлении. Без avoid_overwriting файл с тем же именем заменяется. Ошибка 422 останавливает запрос на этом файле, а ранее сохранённые файлы остаются.
Удаление медиафайла сайта¶
DELETE /media/{filename}
Удаляет медиафайл уровня сайта.
Параметры
| Имя | Тип | Обязательный | Описание |
|---|---|---|---|
filename |
string | Да | Имя удаляемого медиафайла. Может содержать путь подпапки (например, blog/hero.jpg). |
Коды ответов
| Код | Описание |
|---|---|
204 |
Файл удалён |
401 |
Не авторизован |
403 |
Нет разрешения api.media.write |
404 |
Файл не найден |
422 |
Неверное имя файла (сегмент пути пуст, начинается с точки или равен ..) |
Удаляет файл и его сопутствующий файл .meta.yaml (если есть) из директории user/media и исключает его из ручного порядка папки. Параметр filename поддерживает пути подпапок.
Создание папки медиафайлов¶
POST /media/folders
Создаёт новую папку в директории медиафайлов уровня сайта.
Запрос
Ответ
Коды ответов
| Код | Описание |
|---|---|
201 |
Папка создана |
401 |
Не авторизован |
403 |
Нет разрешения api.media.write |
422 |
Ошибка валидации или папка уже существует |
Создаёт новую папку в user/media. Родительские папки создаются автоматически. Тело запроса должно содержать свойство path с относительным путём создаваемой папки. Ни один сегмент пути не может начинаться с точки или быть ... Заголовок Location указывает на список содержимого новой папки (/media?path=...).
Удаление папки медиафайлов¶
DELETE /media/folders/{path}
Удаляет пустую папку из папки медиафайлов уровня сайта.
Параметры
| Имя | Тип | Обязательный | Описание |
|---|---|---|---|
path |
string | Да | Путь папки относительно корня медиафайлов |
Коды ответов
| Код | Описание |
|---|---|
204 |
Папка удалена |
401 |
Не авторизован |
403 |
Нет разрешения api.media.write |
404 |
Папка не найдена |
422 |
Папка не пуста или путь неверен |
Удаляет пустую папку из директории user/media. В папке не должно быть файлов и подпапок, включая скрытые файлы, сопутствующие файлы .meta.yaml и файл порядка media_order.yaml.
Переименование медиафайла сайта¶
POST /media/rename
Переименовывает или перемещает файл в директории медиафайлов уровня сайта.
Запрос
Ответ
{"data": {"filename": "banner.jpg", "path": "blog", "url": "/user/media/blog/banner.jpg", "type": "image/jpeg", "size": 184320, "dimensions": {"width": 1600, "height": 900}, "thumbnail_url": "/api/v1/thumbnails/3f2a9c1e4b5d6a7f8e9d0c1b2a394857.jpg", "modified": "2026-09-01T10:15:00+00:00"}}
Коды ответов
| Код | Описание |
|---|---|
200 |
Файл переименован |
401 |
Не авторизован |
403 |
Нет разрешения api.media.write |
404 |
Исходный файл не найден |
422 |
Ошибка валидации или место назначения уже занято |
Переименовывает файл или перемещает его в другую папку внутри user/media. from и to — относительные пути. Целевая папка при необходимости создаётся автоматически. Сопутствующий файл .meta.yaml тоже перемещается, а ручной порядок папок сохраняется согласованным. Ответ — файл на новом месте.
Новое имя очищается перед использованием: пробелы заменяются дефисом, символы, кроме букв, цифр, ., _ и -, удаляются, а расширение исходного файла сохраняется всегда (любое расширение, указанное в to, заменяется). Так, {"from": "hero.jpg", "to": "My Banner.png"} даёт My-Banner.jpg. Если очищенное имя совпадает с исходным, ничего не меняется и файл возвращается как есть. Очищенное имя, в котором не осталось букв и цифр, возвращает 422.
Переименование папки медиафайлов¶
POST /media/folders/rename
Переименовывает папку в директории медиафайлов уровня сайта.
Запрос
Ответ
Коды ответов
| Код | Описание |
|---|---|
200 |
Папка переименована |
401 |
Не авторизован |
403 |
Нет разрешения api.media.write |
404 |
Исходная папка не найдена |
422 |
Ошибка валидации или место назначения уже занято |
Переименовывает папку внутри user/media. Всё содержимое папки сохраняется. from и to — относительные пути от корня медиафайлов.
Ответ содержит реальные значения children_count (подпапки) и file_count (медиафайлы, без учёта сопутствующих файлов и файла порядка) переименованной папки — те же счётчики, что сообщает список содержимого папки, поэтому клиент может обновить запись, не запрашивая список заново.
Отдача миниатюры¶
GET /thumbnails/{file}
Отдаёт кэшированную миниатюру изображения, созданную службой миниатюр API. Этот эндпоинт публичный и не требует аутентификации. Имена файлов миниатюр — это хеши, создаваемые при сериализации медиафайлов; Admin2 использует URL, встроенные в ответы с медиафайлами (thumbnail_url или avatar_url пользователя), а не запрашивает миниатюры по пути. Ответы приходят с Cache-Control: public, max-age=31536000, immutable, поэтому их можно безопасно кэшировать на год.
Параметры
| Имя | Тип | Обязательный | Описание |
|---|---|---|---|
file |
string | Да | Имя файла миниатюры (только базовое имя). |
Коды ответов
| Код | Описание |
|---|---|
200 |
Миниатюра отдана. |
404 |
Миниатюра не найдена в кэше. |
Миниатюры хранятся в cache://api/thumbnails/. Они создаются при сериализации изображения в ответе с медиафайлами и никогда — этим эндпоинтом, поэтому ещё не кэшированная миниатюра (например, после очистки кэша) возвращает 404, пока список медиафайлов, содержащий её, не будет запрошен снова.
Получение метаданных медиафайла страницы¶
GET /pages/{route}/media/{filename}/meta
Читает редактируемые метаданные медиафайла страницы, хранящиеся в его сопутствующем файле .meta.yaml.
Параметры
| Имя | Тип | Обязательный | Описание |
|---|---|---|---|
route |
string | Да | Маршрут страницы |
filename |
string | Да | Имя медиафайла |
Ответ
{"data": {"filename": "photo.jpg", "has_meta": true, "fields": [{"key": "alt", "label": "Alt Text", "type": "text", "value": "Sunset over the bay"}, {"key": "title", "label": "Title", "type": "text", "value": ""}, {"key": "caption", "label": "Caption", "type": "textarea", "value": ""}, {"key": "description", "label": "Description", "type": "textarea", "value": ""}, {"key": "tags", "label": "Tags", "type": "tags", "value": ["beach", "summer"]}], "extra": {"width": 1920, "height": 1080}}}
Коды ответов
| Код | Описание |
|---|---|
200 |
Успех |
401 |
Не авторизован |
403 |
Нет разрешения api.media.read или правила самой страницы запрещают чтение |
404 |
Страница или файл не найдены |
422 |
Неверное имя файла (начинается с точки или содержит ..) |
Возвращает по одной записи в fields для каждого редактируемого поля, настроенного в разделе Плагины → API → Метаданные медиафайлов (plugins.api.media_metadata.fields), с текущим значением. Если ничего не настроено, по умолчанию используются alt, title, caption, description и tags. Значение поля text или textarea — строка (пустая, если не задано), а значение поля tags — список строк.
Любые другие ключи, хранящиеся в сопутствующем файле (данные EXIF, размеры, сведения о загрузке), возвращаются как данные только для чтения в extra. has_meta сообщает, существует ли сопутствующий файл вообще.
Обновление метаданных медиафайла страницы¶
PATCH /pages/{route}/media/{filename}/meta
Сохраняет редактируемые метаданные медиафайла страницы.
Параметры
| Имя | Тип | Обязательный | Описание |
|---|---|---|---|
route |
string | Да | Маршрут страницы |
filename |
string | Да | Имя медиафайла |
Запрос
Ответ
{"data": {"filename": "photo.jpg", "has_meta": true, "fields": [{"key": "alt", "label": "Alt Text", "type": "text", "value": "Sunset over the bay"}, {"key": "title", "label": "Title", "type": "text", "value": ""}, {"key": "caption", "label": "Caption", "type": "textarea", "value": ""}, {"key": "description", "label": "Description", "type": "textarea", "value": ""}, {"key": "tags", "label": "Tags", "type": "tags", "value": ["beach", "summer"]}], "extra": {"width": 1920, "height": 1080}}}
Коды ответов
| Код | Описание |
|---|---|
200 |
Метаданные сохранены |
401 |
Не авторизован |
403 |
Нет разрешения api.media.write или правила самой страницы запрещают обновление |
404 |
Страница или файл не найдены |
422 |
Неверное имя файла или значение, не являющееся простым текстом |
Передавайте значения в объекте fields или в виде простого отображения ключей полей на значения. Меняются только настроенные поля, присутствующие в запросе, а пустое значение (пустая строка или пустой список для поля tags) удаляет это поле. Ключи, которые не настроены, игнорируются, а все остальные ключи, уже имеющиеся в сопутствующем файле, сохраняются. Ответ — обновлённые метаданные в том же формате, что и в разделе Получение метаданных медиафайла страницы.
Значения выводятся в атрибуты <img> на сайте, поэтому они очищаются при сохранении: HTML-теги и управляющие символы удаляются, пробелы в однострочных полях схлопываются, а каждое значение обрезается до plugins.api.media_metadata.max_length символов (по умолчанию 2000). Значение tags может быть списком строк или одной строкой через запятую; дубликаты и пустые значения отбрасываются, сохраняется не более 50 тегов. Зарезервированные ключи, которыми управляет сам Grav (width, height, mime, size, filesize, modified, upload, type), здесь записать нельзя.
Если удалены все ключи, сопутствующий файл удаляется.
Удаление метаданных медиафайла страницы¶
DELETE /pages/{route}/media/{filename}/meta
Очищает редактируемые метаданные медиафайла страницы.
Параметры
| Имя | Тип | Обязательный | Описание |
|---|---|---|---|
route |
string | Да | Маршрут страницы |
filename |
string | Да | Имя медиафайла |
Коды ответов
| Код | Описание |
|---|---|
204 |
Метаданные очищены |
401 |
Не авторизован |
403 |
Нет разрешения api.media.write или правила самой страницы запрещают обновление |
404 |
Страница или файл не найдены |
422 |
Неверное имя файла (начинается с точки или содержит ..) |
Удаляет все настроенные поля метаданных из сопутствующего файла .meta.yaml этого файла. Другие ключи, например данные EXIF или размеры, сохраняются, а сопутствующий файл удаляется только тогда, когда в нём больше ничего не остаётся. Сам медиафайл не затрагивается.
Отдача исходного медиафайла сайта¶
GET /media/raw/{path}
Передаёт байты медиафайла уровня сайта, который веб-сервер не отдаёт напрямую.
Параметры
| Имя | Тип | Обязательный | Описание |
|---|---|---|---|
path |
string | Да | Путь файла относительно корня медиафайлов. Может содержать / (например, photos/beach.jpg). |
Коды ответов
| Код | Описание |
|---|---|
200 |
Байты файла с определённым типом MIME в Content-Type |
401 |
Не авторизован |
403 |
Нет разрешения api.media.read |
404 |
Файл не найден или не является отдаваемым типом медиафайла |
422 |
Неверный путь (сегмент начинается с точки или равен ..) |
Списки медиафайлов обычно дают каждому файлу прямой статический URL. Когда папка медиафайлов сайта находится там, откуда веб-сервер отказывается отдавать файлы, например в папке user/env/<host>/media при мультисайте (поставляемые с Grav конфигурации .htaccess и nginx запрещают user/env, user/config и user/accounts), url в списке указывает сюда.
Отдаются только изображения, видео, аудио, шрифты и PDF. Любой другой тип файла возвращает 404, поэтому этот маршрут нельзя использовать для чтения исходных файлов или файлов конфигурации. Ответ отправляется с inline, Content-Security-Policy: default-src 'none'; style-src 'unsafe-inline'; sandbox и X-Content-Type-Options: nosniff, поэтому загруженный SVG не может выполнить скрипт при прямом открытии, а также с Cache-Control: private, max-age=600.
Поскольку элемент <img> в браузере не может отправить заголовок аутентификации, этот маршрут принимает cookie сессии самого сайта, а также JWT, переданный параметром запроса ?token=.
Получение метаданных медиафайла сайта¶
GET /media/meta
Читает редактируемые метаданные медиафайла уровня сайта, хранящиеся в его сопутствующем файле .meta.yaml.
Параметры
| Имя | Тип | Обязательный | Описание |
|---|---|---|---|
path |
string | Да | Параметр запроса: путь файла относительно корня медиафайлов (например, blog/hero.jpg) |
Ответ
{"data": {"filename": "hero.jpg", "has_meta": true, "fields": [{"key": "alt", "label": "Alt Text", "type": "text", "value": "Sunset over the bay"}, {"key": "title", "label": "Title", "type": "text", "value": ""}, {"key": "caption", "label": "Caption", "type": "textarea", "value": ""}, {"key": "description", "label": "Description", "type": "textarea", "value": ""}, {"key": "tags", "label": "Tags", "type": "tags", "value": ["beach", "summer"]}], "extra": {"width": 1920, "height": 1080}}}
Коды ответов
| Код | Описание |
|---|---|
200 |
Успех |
401 |
Не авторизован |
403 |
Нет разрешения api.media.read |
404 |
Файл не найден |
422 |
path отсутствует или неверен |
Файл адресуется параметром запроса path, а не в URL, потому что пути медиафайлов сайта содержат косые черты. Ответ такой же, как в разделе Получение метаданных медиафайла страницы: по одной записи на каждое настроенное поле в fields, другие ключи сопутствующего файла в extra, а has_meta сообщает, существует ли сопутствующий файл. filename — базовое имя файла.
Обновление метаданных медиафайла сайта¶
PATCH /media/meta
Сохраняет редактируемые метаданные медиафайла уровня сайта.
Параметры
| Имя | Тип | Обязательный | Описание |
|---|---|---|---|
path |
string | Да | Параметр запроса: путь файла относительно корня медиафайлов (например, blog/hero.jpg) |
Запрос
Ответ
{"data": {"filename": "hero.jpg", "has_meta": true, "fields": [{"key": "alt", "label": "Alt Text", "type": "text", "value": "Sunset over the bay"}, {"key": "title", "label": "Title", "type": "text", "value": ""}, {"key": "caption", "label": "Caption", "type": "textarea", "value": ""}, {"key": "description", "label": "Description", "type": "textarea", "value": ""}, {"key": "tags", "label": "Tags", "type": "tags", "value": ["beach", "summer"]}], "extra": {"width": 1920, "height": 1080}}}
Коды ответов
| Код | Описание |
|---|---|
200 |
Метаданные сохранены |
401 |
Не авторизован |
403 |
Нет разрешения api.media.write |
404 |
Файл не найден |
422 |
path отсутствует или неверен, либо значение не является простым текстом |
Работает так же, как Обновление метаданных медиафайла страницы: меняются только настроенные поля, присутствующие в запросе, пустое значение удаляет поле, другие ключи сопутствующего файла сохраняются, а значения очищаются при сохранении. Ответ — обновлённые метаданные. Чтобы применить одинаковые значения к нескольким файлам за один запрос, используйте Пакетное обновление метаданных медиафайлов сайта.
Удаление метаданных медиафайла сайта¶
DELETE /media/meta
Очищает редактируемые метаданные медиафайла уровня сайта.
Параметры
| Имя | Тип | Обязательный | Описание |
|---|---|---|---|
path |
string | Да | Параметр запроса: путь файла относительно корня медиафайлов (например, blog/hero.jpg) |
Коды ответов
| Код | Описание |
|---|---|
204 |
Метаданные очищены |
401 |
Не авторизован |
403 |
Нет разрешения api.media.write |
404 |
Файл не найден |
422 |
path отсутствует или неверен |
Удаляет все настроенные поля метаданных из сопутствующего файла .meta.yaml этого файла. Другие ключи сохраняются, а сопутствующий файл удаляется только тогда, когда в нём больше ничего не остаётся. Сам медиафайл не затрагивается.
Пакетное обновление метаданных медиафайлов сайта¶
POST /media/batch/meta
Применяет одинаковые поля метаданных к нескольким медиафайлам уровня сайта сразу.
Запрос
Ответ
{"data": {"results": [{"path": "photos/beach.jpg", "status": "success"}, {"path": "photos/missing.jpg", "status": "error", "message": "Media file not found."}], "total": 2, "successful": 1, "failed": 1}}
Коды ответов
| Код | Описание |
|---|---|
200 |
Результаты по каждому файлу (проверяйте каждый status) |
401 |
Не авторизован |
403 |
Нет разрешения api.media.write |
422 |
Отсутствует files или fields, files пуст или не является списком, fields не является объектом, либо слишком много файлов |
files перечисляет пути относительно корня медиафайлов, а fields сопоставляет ключи полей метаданных значениям. В каждый файл записываются только настроенные поля, присутствующие в fields, поэтому пакет, задающий только tags, не трогает собственные alt и title каждого файла. Пустое значение (пустая строка или пустой список для поля tags) удаляет это поле. Значения очищаются так же, как в разделе Обновление метаданных медиафайла сайта.
Каждый файл обрабатывается отдельно: неверный путь или отсутствующий файл попадает в results со status: error и message, а остальная часть пакета всё равно выполняется. Число файлов ограничено plugins.api.batch.max_items (по умолчанию 50).
Задание порядка медиафайлов¶
POST /media/order
Сохраняет ручной порядок файлов в директории медиафайлов уровня сайта.
Запрос
Коды ответов
| Код | Описание |
|---|---|
204 |
Порядок сохранён |
401 |
Не авторизован |
403 |
Нет разрешения api.media.write |
404 |
Папка не найдена |
422 |
Отсутствует массив order или неверен path |
path — папка относительно корня медиафайлов; не указывайте его для корневой папки. order перечисляет имена файлов в нужном порядке. Записи сокращаются до базовых имён файлов, пустые значения отбрасываются. Пустой order удаляет сохранённый порядок.
Порядок хранится в файле media_order.yaml внутри папки, и Список медиафайлов сайта применяет его при выводе содержимого этой папки. Файлы, которых нет в сохранённом порядке (например, новые загрузки), идут после упорядоченных. Сам файл порядка никогда не появляется в списках и результатах поиска и поддерживается в актуальном состоянии при удалении, переименовании или перемещении файла.
Загрузка файла для схемы¶
POST /blueprint-upload
Загружает файл для поля схемы с type: file (логотип темы, ресурс плагина, аватар) и сохраняет его в папку, указанную в destination этого поля.
Параметры
| Имя | Тип | Обязательный | Описание |
|---|---|---|---|
file |
file | Да | Загружаемый файл (multipart/form-data). Подходит любое имя поля, и в одном запросе можно отправить несколько файлов. |
destination |
string | Да | Значение destination поля схемы: поток Grav (theme://images/logo, user://media), токен self@:subpath, разрешаемый относительно scope, или обычный путь относительно user/ |
scope |
string | Нет | Владелец схемы, используемый для разрешения адресов self@:: plugins/<slug>, themes/<slug>, pages/<route> или users/<username> |
field |
string | Нет | Полное имя поля схемы, к которому относится загрузка (custom_css, header.stylesheet). Вместе со scope сервер находит allow_extensions поля в самой схеме. |
random_name |
boolean | Нет | Заменить имя файла случайным, сохранив расширение (по умолчанию: false) |
avoid_overwriting |
boolean | Нет | Добавить префикс с отметкой времени вместо замены существующего файла с тем же именем (по умолчанию: false) |
accept |
string | Нет | Список разрешённых расширений через запятую (.pdf, *.jpg) или шаблонов MIME (image/*) |
filesize |
number | Нет | Максимальный размер для поля в МБ. Может только уменьшить предел 64 МБ. |
Ответ
{"data": [{"name": "logo.png", "path": "user/themes/quark/images/logo/logo.png", "size": 20480, "type": "image/png", "url": "https://example.com/user/themes/quark/images/logo/logo.png"}]}
Коды ответов
| Код | Описание |
|---|---|
201 |
Файлы сохранены |
401 |
Не авторизован |
403 |
Нет разрешения api.media.write, цель находится в user/config/ или user/env/*/config/, либо используется область users/<username> другого аккаунта без api.users.write |
422 |
Отсутствует destination, нет файла, небезопасный путь или отклонённые имя, тип либо размер файла |
Это повторяет taskFilesUpload классической админки и используется Admin2 для полей схем с типом «файл», у которых задан destination. Отправляйте как multipart/form-data. Абсолютные пути и сегменты .. в destination отклоняются.
Ответ перечисляет каждый сохранённый файл. path — логический путь под user/, построенный из destination и scope, а не разрешённый путь на диске, поэтому он работает и через символически связанные папки тем или плагинов. Передайте его в Удаление файла схемы, чтобы удалить файл.
Правила для файлов:
- Размер каждого файла ограничен 64 МБ, а собственный
filesizeполя может только уменьшить этот предел. - Ни одна разделённая точками часть имени не должна входить в
security.uploads_dangerous_extensions, поэтомуshell.php.jpgотклоняется. - Файлы конфигурации и данных (
yaml,yml,json,twig,env,neon,lock) отклоняются везде, куда бы они ни попали. Содержимое страниц (md,markdown) и таблицы стилей (css,scss,sass,less) тоже отклоняются, если только поле, указанное вfield, не разрешает их черезallow_extensionsв схеме, которой принадлежитscope, и загрузка идёт в собственныйdestinationэтого поля. - Загрузки в
user/accounts/могут быть только изображениями (jpg,jpeg,png,gif,webp,svg,avif,bmp,ico), так как Grav читает эту папку как хранилище учётных записей. - Загрузки, которые попадают в
user/config/илиuser/env/*/config/, отклоняются с кодом 403. - Файлы SVG санируются после сохранения.
Для адреса self@: с областью users/<username> вашего собственного аккаунта нужно только api.media.write. Для другого аккаунта дополнительно нужно api.users.write (или права суперпользователя).
Удаление файла схемы¶
DELETE /blueprint-upload
Удаляет файл, сохранённый полем схемы с типом «файл», а также его сопутствующий файл .meta.yaml, если он есть.
Параметры
| Имя | Тип | Обязательный | Описание |
|---|---|---|---|
path |
string | Да | Логический путь файла относительно папки user (префикс user/ необязателен) |
scope |
string | Нет | Владелец схемы поля: plugins/<slug>, themes/<slug>, pages/<route> или users/<username>. Нужен только вместе с field. |
field |
string | Нет | Полное имя поля схемы, которому принадлежит файл. Вместе со scope позволяет allow_extensions поля разрешить удаление собственных файлов. |
Запрос
Коды ответов
| Код | Описание |
|---|---|
204 |
Файл удалён или уже отсутствовал |
401 |
Не авторизован |
403 |
Нет разрешения api.media.write, цель находится в user/config/ или user/env/*/config/, файл в user/accounts/ не является изображением, либо это файл другого аккаунта без api.users.write |
422 |
Отсутствует path, в нём есть обход пути или нулевые байты, отклонён тип файла, либо цель не является обычным файлом |
path — логический путь, который вернула загрузка, относительно папки user; префикс user/ необязателен. .. и нулевые байты отклоняются.
Действуют те же правила расширений, что и в разделе Загрузка файла для схемы, поэтому через этот эндпоинт нельзя удалить файлы конфигурации, а также содержимое страниц (.md, .markdown) и таблицы стилей (.css, .scss, .sass, .less), если только field и scope не указывают поле, схема которого разрешает их через allow_extensions, и файл находится в собственной папке этого поля. В user/accounts/ можно удалять только файлы изображений, а без api.users.write (или прав суперпользователя) — только собственный аватар, то есть файл, на который указывает поле avatar вашего аккаунта.
Вызов идемпотентен: файл, которого больше нет, возвращает 204.