API: Медиафайлы
Загрузка, скачивание и управление файлами в облаке Google Drive. Префикс: /media. Файл: srv/app/api/endpoints/media.py
Обзор эндпоинтов
| Метод | Путь | Описание |
|---|---|---|
| POST | /media/upload | Загрузить файл на Google Drive (до 4 ГБ) |
| GET | /media/{file_id} | Скачать / стримить медиафайл |
| GET | /media/size/{file_id} | Получить метаданные и размер файла |
| POST | /media/copy | Дублировать файл на Google Drive (для пересылки) |
Google Drive Resumable Upload
Для загрузки файлов на Google Drive бэкенд использует механизм возобновляемой загрузки (Resumable Upload). Это позволяет стабильно отправлять файлы до 4 ГБ порциями по 5 МБ.
Поскольку FastAPI считывает файлы в виде неперемещаемого потока данных, реализован специальный враппер SeekableFastAPIStream, который добавляет поддержку метода seek() и tell(), необходимых библиотеке Google API Client.
class SeekableFastAPIStream(io.RawIOBase):
def __init__(self, raw_file):
self.raw_file = raw_file
self._position = 0
def readinto(self, b):
chunk = self.raw_file.read(len(b))
if not chunk: return 0
n = len(chunk)
b[:n] = chunk
self._position += n
return n
def seek(self, offset, whence=io.SEEK_SET):
# Реализация seek для поддержки чанков Google SDK...
return self._position
Контроль квоты диска
Каждому пользователю выделена квота дискового пространства (по умолчанию 100 ГБ, настраивается через HOME_USER_QUOTA_BYTES).
Перед каждым сохранением нового файла бэкенд высчитывает суммарный размер файлов пользователя. Если новая загрузка превышает лимит, запускается автоматическая очистка: старые файлы пользователя последовательно удаляются из Google Drive и БД (начиная с самых ранних), пока не освободится достаточно места. Аватар пользователя защищен от автоматического удаления.
Копирование файлов (POST /media/copy)
При пересылке медиафайла другому пользователю клиент не загружает его повторно. Вместо этого вызывается POST /media/copy, который выполняет быстрое копирование файла внутри облака Google Drive (через API) без скачивания на сервер. При этом создается новая запись MediaItem, привязанная к квоте пересылающего пользователя.