Repository navigation
Doc How Images
Картинка тура проходит путь: загрузка в Media, привязка к туру в Catalog, открытие при публикации, отдача по постоянному адресу с долгим кэшем.
- Менеджер на шаге «Фото» выбирает
beach.jpg. Фронтенд отправляетPOST /api/v1/media/upload?purpose=tour-imageи получаетidфайла. - Мастер сохраняет список фото:
PUT /api/v1/catalog/manage/tours/{id}/imagesсmediaFileId, порядком, обложкой и alt. - В мастере менеджер видит превью через
/api/v1/media/manage/files/{fileId}/w800. - Менеджер публикует тур. Catalog вызывает у Media
MarkMediaFilesPublic. - Гость открывает каталог, браузер грузит
/api/v1/media/files/{fileId}/w800. Ответ кэшируется на год.
При загрузке фото тура Media делает три превью: w200, w800, w1600. Каждое вписывается в свою ширину с сохранением пропорций и без увеличения: из оригинала шириной 1000 px превью w1600 останется шириной 1000 px. Формат превью тот же, что у оригинала.
Где какой размер на фронтенде (src/utils/media.ts):
| Вариант | Основной размер |
srcset до |
Где |
|---|---|---|---|
card |
w800 |
w1600 |
карточки каталога и избранного |
gallery |
w1600 |
w1600 |
галерея страницы тура |
thumb |
w200 |
w800 |
миниатюры |
Адрес строится из id: mediaImageUrl(id, size) для публичных, manageMediaFileUrl(id, size) для черновика. Сервер адресов не отдаёт.
- У каждого файла флаг
IsPublic, по умолчаниюfalse. - Публичный адрес
/media/files/…для закрытого файла отвечает 404. Так фото черновика не утекают по прямой ссылке. - Флаг ставит только Catalog (gRPC
MarkMediaFilesPublic): при публикации тура и приPUT images, если тур уже опубликован. Media ставит флаг только у активных файлов с назначениемtour-image. Флаг не снимается: после снятия тура с публикации карточка в избранном продолжает показывать обложку. - Замена или добавление фото у уже опубликованного тура открывает новые файлы до сохранения списка. Если Media недоступен, ответ 503 и фото тура остаются прежними. У черновика флаг не ставится (см. Конструктор и публикация тура).
| Адрес | Cache-Control |
Почему |
|---|---|---|
/media/files/{id}/{size} |
public, max-age=31536000, immutable |
содержимое по id никогда не меняется: новое фото получает новый id |
/media/manage/files/{id}/{size} |
private, no-store |
доступ зависит от пользователя |
| Что | Значение | Где проверяется |
|---|---|---|
| размер файла | до 10 МБ | Media; nginx режет тело больше 12 МБ (413) |
| типы фото тура | jpeg, png, webp | Media |
| фото в туре | до 20 | Catalog |
| для публикации | не меньше 3 фото и одна обложка | Catalog |
| ширина обложки | от 1280 px по оригиналу | Catalog по данным GetMediaFiles
|
| чьё фото | файл должен принадлежать владельцу тура. Чужой и неизвестный id дают один и тот же 422 images.notFound: по ответу нельзя понять, существует ли файл |
Catalog по данным GetMediaFiles
|
| назначение | к туру прикрепляется только tour-image. Другое назначение даёт тот же 422 images.notFound
|
Catalog по полю purpose из GetMediaFiles
|
Сидер Media кладёт демо-фото с фиксированными id (WebP), сидер Catalog привязывает их к демо-турам. Источники и лицензии фото указаны в README репозитория.
Система
API
Сервисы
Как реализовано
Справочное
- Видение продукта
- Дорожная карта
- Этап 1: что осталось
- Этап 2: расширение
- Этап 3: масштабирование
- Концепция сайта и интерфейса
- Шаблон ТЗ