299 lines
10 KiB
Markdown
299 lines
10 KiB
Markdown
# 📤 API загрузки файлов с квотами - Точная документация
|
||
|
||
## Обзор
|
||
|
||
Quoter предоставляет API для загрузки файлов с системой квот и автоматической обработкой различных типов медиа.
|
||
|
||
## Базовый URL
|
||
```
|
||
http://localhost:8080
|
||
```
|
||
|
||
## Аутентификация
|
||
Все эндпоинты загрузки требуют JWT токен в заголовке:
|
||
```
|
||
Authorization: Bearer <jwt-token>
|
||
```
|
||
|
||
---
|
||
|
||
## 📤 Загрузка файлов (УЛУЧШЕННАЯ ВЕРСИЯ)
|
||
|
||
### POST /
|
||
|
||
Загружает файл(ы) в S3-совместимое хранилище (Storj) с улучшенной проверкой квот и валидацией.
|
||
|
||
#### Заголовки запроса
|
||
```http
|
||
Authorization: Bearer <jwt-token>
|
||
Content-Type: multipart/form-data
|
||
```
|
||
|
||
#### Параметры
|
||
- **file** (required) - файл(ы) для загрузки в multipart/form-data
|
||
|
||
#### Поддерживаемые форматы
|
||
Автоматическое определение MIME-типа из содержимого файла:
|
||
- **Изображения**: JPEG, PNG, GIF, WebP, HEIC
|
||
- **Видео**: MP4, WebM, AVI
|
||
- **Аудио**: MP3, WAV, OGG
|
||
- **Документы**: PDF
|
||
|
||
#### 🔄 Улучшенная логика обработки
|
||
|
||
1. **Проверка авторизации** - извлечение и валидация JWT токена
|
||
2. **Получение текущей квоты** пользователя из Redis
|
||
3. **Предварительная проверка квоты** - пользователь не достиг лимита
|
||
4. **Streaming чтение файла** с проверками на каждом chunk:
|
||
- Проверка лимита одного файла (500 МБ)
|
||
- Проверка общей квоты пользователя
|
||
5. **Пропуск пустых файлов**
|
||
6. **Определение MIME-типа** из содержимого (не из расширения!)
|
||
7. **Генерация UUID имени** файла с правильным расширением
|
||
8. **Загрузка в Storj S3**
|
||
9. **Обновление квоты** пользователя
|
||
10. **Сохранение метаданных** в Redis (с обработкой ошибок)
|
||
|
||
#### Ограничения
|
||
|
||
- **Максимальная квота на пользователя**: 5 ГБ (5,368,709,120 байт)
|
||
- **Максимальный размер одного файла**: 500 МБ (524,288,000 байт)
|
||
- **Проверка квоты происходит во время чтения** (streaming)
|
||
- **Поддержка множественных файлов** в одном запросе
|
||
|
||
#### Успешные ответы
|
||
|
||
**Один файл:**
|
||
```http
|
||
HTTP/1.1 200 OK
|
||
Content-Type: text/plain
|
||
|
||
```
|
||
|
||
**Несколько файлов:**
|
||
```http
|
||
HTTP/1.1 200 OK
|
||
Content-Type: application/json
|
||
|
||
```
|
||
|
||
#### Коды ошибок (ИСПРАВЛЕННЫЕ)
|
||
|
||
| Код | Условие | Описание |
|
||
|-----|---------|----------|
|
||
| **400 Bad Request** | Нет файлов | `"No files provided or all files were empty"` |
|
||
| **401 Unauthorized** | Отсутствует токен | `"Authorization token required"` |
|
||
| **401 Unauthorized** | Неверный токен | `"Invalid authorization token"` |
|
||
| **413 Payload Too Large** | 🎯 Превышена квота | `"Author quota limit exceeded"` |
|
||
| **413 Payload Too Large** | 🎯 Большой файл | `"Single file size limit exceeded"` |
|
||
| **413 Payload Too Large** | 🎯 Превышение при загрузке | `"Author quota limit would be exceeded"` |
|
||
| **415 Unsupported Media Type** | Неподдерживаемый MIME | `"Unsupported file format"` |
|
||
| **415 Unsupported Media Type** | Нет расширения для MIME | `"Unsupported content type"` |
|
||
| **500 Internal Server Error** | Ошибка S3 | `"File upload failed"` |
|
||
| **500 Internal Server Error** | Ошибка квоты | `"Failed to update user quota"` |
|
||
|
||
#### ✅ Исправленные проблемы
|
||
|
||
1. **Правильный код ошибки для квоты**: 413 Payload Too Large
|
||
2. **Efficient memory usage**: streaming с проверками на каждом chunk
|
||
3. **Предварительная проверка квоты** перед началом загрузки
|
||
4. **Лимит размера одного файла**: 500 МБ
|
||
5. **Улучшенная обработка ошибок** с детальными сообщениями
|
||
6. **Поддержка множественных файлов** в одном запросе
|
||
7. **Детальное логирование** с процентом использования квоты
|
||
|
||
---
|
||
|
||
#### 🔄 Как это работает
|
||
|
||
1. **JWT декодирование** - извлекается `user_id` из токена
|
||
2. **Redis lookup** - опциональный поиск сессии по ключу `session:{user_id}:{token}`
|
||
3. **Quota lookup** - получение квоты по ключу `quota:{user_id}` из Redis
|
||
4. **Activity update** - обновление `last_activity` timestamp (если сессия найдена)
|
||
5. **Response building** - объединение данных пользователя и квоты
|
||
|
||
#### Заголовки запроса
|
||
```http
|
||
Authorization: Bearer <jwt-token>
|
||
```
|
||
|
||
#### Успешный ответ
|
||
```http
|
||
HTTP/1.1 200 OK
|
||
Content-Type: application/json
|
||
|
||
```
|
||
|
||
#### Поля ответа
|
||
|
||
| Поле | Тип | Описание |
|
||
|------|-----|----------|
|
||
| `user_id` | string | Уникальный ID пользователя |
|
||
| `username` | string \| null | Имя пользователя |
|
||
| `token_type` | string \| null | Тип токена (обычно "session") |
|
||
| `created_at` | string \| null | Unix timestamp создания сессии |
|
||
| `last_activity` | string \| null | Unix timestamp последней активности |
|
||
| `auth_data` | string \| null | JSON-строка с данными авторизации |
|
||
| `device_info` | string \| null | JSON-строка с информацией об устройстве |
|
||
| `quota.current_quota` | number | Текущее использование квоты в байтах |
|
||
| `quota.max_quota` | number | Максимальная квота в байтах |
|
||
| `quota.usage_percentage` | number | Процент использования квоты |
|
||
|
||
#### Коды ошибок
|
||
|
||
| Код | Условие | Описание |
|
||
|-----|---------|----------|
|
||
| **401 Unauthorized** | Отсутствует токен | `"Authorization token required"` |
|
||
| **401 Unauthorized** | Неверный JWT | `"Invalid or expired session token"` |
|
||
| **401 Unauthorized** | Сессия не найдена | `"Session not found or expired"` |
|
||
|
||
#### Примеры использования
|
||
|
||
```bash
|
||
# Получение информации о текущем пользователе
|
||
curl -H "Authorization: Bearer eyJ0eXAiOiJKV1QiLCJhbGc..." \
|
||
http://localhost:8080/
|
||
```
|
||
|
||
---
|
||
|
||
## 📊 Управление квотами
|
||
|
||
### GET /quota
|
||
|
||
Получает информацию о квоте пользователя.
|
||
|
||
#### Параметры запроса
|
||
```
|
||
GET /quota?user_id=<user_id>
|
||
```
|
||
|
||
#### Ответ
|
||
```json
|
||
{
|
||
"user_id": "user123",
|
||
"current_quota": 1073741824,
|
||
"max_quota": 5368709120
|
||
}
|
||
```
|
||
|
||
### POST /quota/increase
|
||
|
||
Увеличивает квоту пользователя (admin-only).
|
||
|
||
#### Тело запроса
|
||
```json
|
||
{
|
||
"user_id": "user123",
|
||
"additional_bytes": 1073741824
|
||
}
|
||
```
|
||
|
||
#### Валидация
|
||
- `additional_bytes` должно быть > 0
|
||
- Требуется админский токен
|
||
|
||
### POST /quota/set
|
||
|
||
Устанавливает абсолютное значение квоты (admin-only).
|
||
|
||
#### Тело запроса
|
||
```json
|
||
{
|
||
"user_id": "user123",
|
||
"new_quota_bytes": 2147483648
|
||
}
|
||
```
|
||
|
||
---
|
||
|
||
## 🔍 Получение файлов
|
||
|
||
### GET /{filename}
|
||
|
||
Возвращает файл по имени с возможными трансформациями.
|
||
|
||
#### Параметры URL
|
||
- `filename` - имя файла или имя_размер.расширение для миниатюр
|
||
|
||
#### Query параметры
|
||
- `s=<shout_id>` - добавляет оверлей с данными shout (только изображения)
|
||
|
||
#### Примеры
|
||
```bash
|
||
GET /uuid-file.jpg # Оригинальный файл
|
||
GET /uuid-file_300.jpg # Миниатюра 300px
|
||
GET /uuid-file_300.jpg/webp # Миниатюра в WebP
|
||
GET /uuid-file.jpg?s=123 # С оверлеем shout
|
||
```
|
||
|
||
---
|
||
|
||
## 🧪 Примеры использования
|
||
|
||
### Загрузка файла
|
||
```bash
|
||
curl -X POST http://localhost:8080/ \
|
||
-H "Authorization: Bearer eyJ0eXAiOiJKV1QiLCJhbGc..." \
|
||
-F "file=@photo.jpg"
|
||
```
|
||
|
||
**Ответ при успехе:**
|
||
```
|
||
c4ca4238-a0b9-23f1-8429-81dc9bdb9a1f.jpg
|
||
```
|
||
|
||
**Ответ при превышении квоты:**
|
||
```
|
||
HTTP/1.1 401 Unauthorized
|
||
Quota exceeded
|
||
```
|
||
|
||
### Проверка квоты
|
||
```bash
|
||
curl "http://localhost:8080/quota?user_id=user123" \
|
||
-H "Authorization: Bearer admin-token"
|
||
```
|
||
|
||
### Увеличение квоты (admin)
|
||
```bash
|
||
curl -X POST http://localhost:8080/quota/increase \
|
||
-H "Authorization: Bearer admin-token" \
|
||
-H "Content-Type: application/json" \
|
||
-d '{"user_id": "user123", "additional_bytes": 1073741824}'
|
||
```
|
||
|
||
---
|
||
|
||
## 🔧 Рекомендации по улучшению
|
||
|
||
1. **Исправить код ошибки квоты**: 401 → 413
|
||
2. **Добавить предварительную проверку размера** из Content-Length
|
||
3. **Streaming загрузка** вместо полного чтения в память
|
||
4. **Лимит размера одного файла**
|
||
5. **Детальная валидация MIME-типов**
|
||
6. **Метрики использования квот**
|
||
|
||
---
|
||
|
||
*Документация актуальна для версии кода на момент создания. Для изменений см. CHANGELOG.md.*
|