205 lines
7.5 KiB
Markdown
205 lines
7.5 KiB
Markdown
|
|
# 📐 Формат URL для ресайзера изображений
|
|||
|
|
|
|||
|
|
## Обзор
|
|||
|
|
|
|||
|
|
Quoter поддерживает автоматическое изменение размера изображений через URL параметры. Система автоматически генерирует миниатюры в предопределенных размерах и возвращает ближайший подходящий размер.
|
|||
|
|
|
|||
|
|
## 🎯 Поддерживаемые размеры
|
|||
|
|
|
|||
|
|
### Предопределенные ширины
|
|||
|
|
```rust
|
|||
|
|
[10, 40, 110, 300, 600, 800, 1400] // пикселей по ширине
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
- **10px** - микро-превью
|
|||
|
|
- **40px** - аватары, иконки
|
|||
|
|
- **110px** - маленькие превью
|
|||
|
|
- **300px** - средние превью
|
|||
|
|
- **600px** - стандартные изображения
|
|||
|
|
- **800px** - большие изображения
|
|||
|
|
- **1400px** - максимальный размер
|
|||
|
|
|
|||
|
|
## 📝 Синтаксис URL
|
|||
|
|
|
|||
|
|
### 1. Современный формат (рекомендуется)
|
|||
|
|
```
|
|||
|
|
GET /{filename}_{width}.{extension}
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
**Примеры:**
|
|||
|
|
```bash
|
|||
|
|
# Запрос изображения шириной 300px
|
|||
|
|
GET /439efaa0-816f-11ef-b201-439da98539bc_300.jpg
|
|||
|
|
|
|||
|
|
# Запрос изображения шириной 600px
|
|||
|
|
GET /5627e002-0c53-11ee-9565-0242ac110006_600.png
|
|||
|
|
|
|||
|
|
# Запрос оригинального размера (без ресайза)
|
|||
|
|
GET /439efaa0-816f-11ef-b201-439da98539bc.jpg
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
### 2. Legacy формат (поддерживается)
|
|||
|
|
```
|
|||
|
|
GET /unsafe/{width}x/production/image/{filename}.{extension}
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
**Примеры:**
|
|||
|
|
```bash
|
|||
|
|
# Legacy формат с указанием ширины
|
|||
|
|
GET /unsafe/1440x/production/image/439efaa0-816f-11ef-b201-439da98539bc.jpg
|
|||
|
|
|
|||
|
|
# Legacy формат без ресайза
|
|||
|
|
GET /unsafe/production/image/5627e002-0c53-11ee-9565-0242ac110006.png
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
### 3. Конверсия формата
|
|||
|
|
```
|
|||
|
|
GET /{filename}.{extension}/webp
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
**Примеры:**
|
|||
|
|
```bash
|
|||
|
|
# Конверсия в WebP
|
|||
|
|
GET /439efaa0-816f-11ef-b201-439da98539bc.jpg/webp
|
|||
|
|
|
|||
|
|
# Конверсия с ресайзом
|
|||
|
|
GET /439efaa0-816f-11ef-b201-439da98539bc_600.jpg/webp
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
## 🔧 Логика обработки
|
|||
|
|
|
|||
|
|
### Алгоритм выбора размера
|
|||
|
|
1. **Точное совпадение**: Если запрошенная ширина есть в предопределенных размерах
|
|||
|
|
2. **Ближайший размер**: Выбирается размер с минимальной разностью
|
|||
|
|
3. **Максимальный лимит**: Если запрошенная ширина > 1400px, возвращается 1400px
|
|||
|
|
4. **Оригинал**: Если ширина не указана (0), возвращается оригинальное изображение
|
|||
|
|
|
|||
|
|
### Примеры выбора размера
|
|||
|
|
```bash
|
|||
|
|
# Запрос 150px → вернет 110px (ближайший меньший)
|
|||
|
|
# Запрос 250px → вернет 300px (ближайший больший)
|
|||
|
|
# Запрос 2000px → вернет 1400px (максимальный)
|
|||
|
|
# Запрос 299px → вернет 300px (ближайший)
|
|||
|
|
# Запрос 301px → вернет 300px (ближайший)
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
### Генерация миниатюр
|
|||
|
|
- **Lazy generation**: Миниатюры создаются по первому запросу
|
|||
|
|
- **Асинхронная обработка**: Генерация происходит в фоне
|
|||
|
|
- **Кэширование**: Созданные миниатюры сохраняются в S3
|
|||
|
|
- **Fallback**: При отсутствии миниатюры возвращается оригинал
|
|||
|
|
|
|||
|
|
## 🎨 Поддерживаемые форматы
|
|||
|
|
|
|||
|
|
### Входные форматы
|
|||
|
|
- **JPEG** (`.jpg`, `.jpeg`)
|
|||
|
|
- **PNG** (`.png`)
|
|||
|
|
- **GIF** (`.gif`)
|
|||
|
|
- **WebP** (`.webp`)
|
|||
|
|
- **HEIC** (`.heic`, `.heif`) - конвертируется в JPEG
|
|||
|
|
- **TIFF** (`.tiff`, `.tif`) - конвертируется в JPEG
|
|||
|
|
|
|||
|
|
### Выходные форматы
|
|||
|
|
- **Сохраняется исходный формат** (кроме HEIC/TIFF → JPEG)
|
|||
|
|
- **WebP конверсия** через `/webp` суффикс
|
|||
|
|
- **Автоматическая оптимизация** для web
|
|||
|
|
|
|||
|
|
## 🚀 HTTP заголовки
|
|||
|
|
|
|||
|
|
### Кэширование
|
|||
|
|
```http
|
|||
|
|
ETag: "filename.ext"
|
|||
|
|
Cache-Control: public, max-age=31536000, immutable
|
|||
|
|
Access-Control-Allow-Origin: *
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
### Условные запросы
|
|||
|
|
```http
|
|||
|
|
# Клиент отправляет
|
|||
|
|
If-None-Match: "filename.ext"
|
|||
|
|
|
|||
|
|
# Сервер отвечает (если не изменено)
|
|||
|
|
HTTP/1.1 304 Not Modified
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
## 💡 Оптимизация производительности
|
|||
|
|
|
|||
|
|
### Клиентская оптимизация
|
|||
|
|
```html
|
|||
|
|
<!-- Используйте srcset для разных размеров -->
|
|||
|
|
<img src="/image_600.jpg"
|
|||
|
|
srcset="/image_300.jpg 300w,
|
|||
|
|
/image_600.jpg 600w,
|
|||
|
|
/image_800.jpg 800w"
|
|||
|
|
sizes="(max-width: 600px) 300px, 600px"
|
|||
|
|
alt="Описание">
|
|||
|
|
|
|||
|
|
<!-- WebP с fallback -->
|
|||
|
|
<picture>
|
|||
|
|
<source srcset="/image_600.jpg/webp" type="image/webp">
|
|||
|
|
<img src="/image_600.jpg" alt="Описание">
|
|||
|
|
</picture>
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
### API использование
|
|||
|
|
```javascript
|
|||
|
|
// Функция для получения оптимального URL
|
|||
|
|
function getImageUrl(filename, maxWidth) {
|
|||
|
|
const sizes = [10, 40, 110, 300, 600, 800, 1400];
|
|||
|
|
const optimalSize = sizes.find(size => size >= maxWidth) || 1400;
|
|||
|
|
|
|||
|
|
const [name, ext] = filename.split('.');
|
|||
|
|
return `https://files.dscrs.site/${name}_${optimalSize}.${ext}`;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// Примеры использования
|
|||
|
|
const thumbUrl = getImageUrl('image.jpg', 300); // image_300.jpg
|
|||
|
|
const fullUrl = getImageUrl('image.jpg', 1200); // image_1400.jpg
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
## 🔍 Мониторинг и отладка
|
|||
|
|
|
|||
|
|
### Логи сервера
|
|||
|
|
```log
|
|||
|
|
# Успешная обработка
|
|||
|
|
INFO GET image_300.jpg [START]
|
|||
|
|
INFO Parsed request - base: image, width: 300, ext: jpg
|
|||
|
|
INFO Cache hit for image.jpg, returning 304
|
|||
|
|
|
|||
|
|
# Генерация миниатюры
|
|||
|
|
WARN Thumbnail not found, generating: image_300.jpg
|
|||
|
|
WARN generate new thumb files: image.jpg
|
|||
|
|
INFO Generated thumbnail: image_300.jpg
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
### Проверка через API
|
|||
|
|
```bash
|
|||
|
|
# Проверка существования файла
|
|||
|
|
curl -I https://files.dscrs.site/image_300.jpg
|
|||
|
|
|
|||
|
|
# Проверка с условным запросом
|
|||
|
|
curl -H "If-None-Match: \"image.jpg\"" https://files.dscrs.site/image_300.jpg
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
## ⚠️ Ограничения и рекомендации
|
|||
|
|
|
|||
|
|
### Лимиты
|
|||
|
|
- **Максимальная ширина**: 1400px
|
|||
|
|
- **Поддерживаемые форматы**: см. список выше
|
|||
|
|
- **Размер файла**: до 500MB для загрузки
|
|||
|
|
|
|||
|
|
### Рекомендации
|
|||
|
|
1. **Используйте WebP** для лучшего сжатия
|
|||
|
|
2. **Кэшируйте на CDN** для лучшей производительности
|
|||
|
|
3. **Указывайте размеры заранее** для избежания layout shift
|
|||
|
|
4. **Используйте lazy loading** для изображений вне viewport
|
|||
|
|
|
|||
|
|
### Troubleshooting
|
|||
|
|
```bash
|
|||
|
|
# Если изображение не отображается
|
|||
|
|
1. Проверьте формат файла (поддерживается ли)
|
|||
|
|
2. Проверьте размер запроса (не превышает ли лимиты)
|
|||
|
|
3. Проверьте логи сервера на ошибки генерации
|
|||
|
|
4. Убедитесь в корректности URL формата
|
|||
|
|
```
|