6.9 KiB
Модуль Хранилища (Storage) - Техническая Документация
1. Обзор
Модуль Storage отвечает за централизованное управление файлами на платформе (аватары, медиа в чатах, вложения в историях). Модуль выступает абстракцией над S3-совместимым объектным хранилищем (в данный момент реализовано через MinIO) и интегрируется с криптографическим ядром для обеспечения безопасности файлов.
Ключевая особенность: модуль реализует концепцию Zero-Knowledge At-Rest Encryption — ни один файл не попадает на жесткие диски S3-сервера в открытом виде.
2. Архитектура и Процесс Загрузки
Сервис S3FileStorageService (реализация IFileStorageService из Shared Kernel) прогоняет файлы через строго определенный пайплайн:
1. Временное буферизирование
Поскольку поток загрузки (HTTP Request Stream) зачастую нельзя читать дважды (отсутствует Seek), файл сначала сохраняется во временную директорию ОС.
2. Абсолютная дедупликация (SHA-256)
Модуль вычисляет криптографический SHA-256 хэш от содержимого загруженного файла.
Именно этот хэш (вместе с расширением) становится именем файла (Object Key) в корзине (Bucket) S3.
- Результат: Если тысяча пользователей перешлет друг другу один и тот же мем (файл), физически в S3 он будет загружен и сохранен ровно один раз, колоссально экономя место на серверах.
3. "На лету" Шифрование (E2EE/At-Rest)
Далее применяется IEncryptionService (обычно AES-256-CBC).
На основе временного файла открывается CryptoStream, который шифрует байты файла "на лету" во второй временный файл. Случайный Вектор Инициализации (Initalization Vector, IV) генерируется сервисом уникально для каждого файла.
4. Загрузка в S3 с Метаданными
Зашифрованный бинарник улетает в MinIO. Чувствительная информация сохраняется совершенно безопасно в заголовках метаданных объекта (MinIO Object MetaData):
ContentType: Исходный MIME-тип (например,image/png).OriginalFileName: Закодированное исходное имя файла (Urlescaped).IV: Вектор инициализации (Base64), необходимый для последующей расшифровки. Без секретного мастер-ключа приложения этот IV бесполезен.EncryptionAlgorithm: Маркер алгоритма (AES-256-CBC).
В конце цикла бэкенд зачищает локальные временные файлы.
3. Процесс Скачивания и Кэширование (API)
Модуль предоставляет минималистичный REST API интерфейс, реализованный через Carter (FilesEndpoints).
Эндпоинты
| Метод | Маршрут | Параметры | Описание |
|---|---|---|---|
GET |
/api/files/{id} |
?download=true |
Отдает расшифрованный файл. Поддерживает Range запросы для стриминга видео и музыки. |
Механизм In-Memory Caching (Производительность)
Расшифровка файлов (особенно видео) в реальном времени и постоянный запрос их из S3 съедает процессорное время и сетевой канал бэкенда.
К эндпоинту скачивания подключен IMemoryCache:
- При первом запросе файла (например, аватара популярного пользователя), он скачивается из MinIO во временный файл ОС на бэкенде.
- Файл прогоняется через
CryptoStream(с использованиемIVиз метаданных корзины S3) для дешифровки и выгрузки вMemoryStream. - Байты готового файла, его
ContentTypeи исходное имя кэшируются в RAM бэкенда на 30 минут (Sliding Expiration). - Все последующие запросы отдают готовые байты прямо из оперативной памяти без сетевого похода в MinIO и без повторной расшифровки.
Поддержка Range-запросов
API использует метод Results.File(..., enableRangeProcessing: true). Это означает, что плееры в браузере или мобильном клиенте могут запрашивать видео кусками (например, Range: bytes=1000-2000), и бэкенд корректно отдаст только нужный чанк (из кэша или после скачивания), что делает модуль пригодным для видео-стриминга прямо из коробки.
Итог
Модуль представляет собой пуленепробиваемый шлюз для работы с медиа:
- Обеспечивает полную конфиденциальность (ни один файл не хранится открытым в корзине облака).
- Защищен от дубликатов (переиспользование за счет SHA-256 хэшей).
- Высоко оптимизирован для раздачи горячего контента (In-Memory кэширование и поддержка HTTP Range Streaming).