# Модуль Хранилища (Storage) - Техническая Документация ## 1. Обзор **Модуль Storage** отвечает за централизованное управление файлами на платформе (аватары, медиа в чатах, вложения в историях). Модуль выступает абстракцией над S3-совместимым объектным хранилищем (в данный момент реализовано через **MinIO**) и интегрируется с криптографическим ядром для обеспечения безопасности файлов. Ключевая особенность: модуль реализует концепцию **Zero-Knowledge At-Rest Encryption** — ни один файл не попадает на жесткие диски S3-сервера в открытом виде. ## 2. Архитектура и Процесс Загрузки Сервис [S3FileStorageService](file:///e:/GIT/forkmessager/backend/src/Modules/Storage/Infrastructure/Storage/S3FileStorageService.cs#21-27) (реализация [IFileStorageService](file:///e:/GIT/forkmessager/backend/src/Shared/Knot.Shared.Kernel/Storage/IFileStorageService.cs#6-26) из 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](file:///e:/GIT/forkmessager/backend/src/Modules/Storage/Presentation/Endpoints/FilesEndpoints.cs#11-54)). ### Эндпоинты | Метод | Маршрут | Параметры | Описание | | :--- | :--- | :--- | :--- | | `GET` | `/api/files/{id}` | `?download=true` | Отдает расшифрованный файл. Поддерживает `Range` запросы для стриминга видео и музыки. | ### Механизм In-Memory Caching (Производительность) Расшифровка файлов (особенно видео) в реальном времени и постоянный запрос их из S3 съедает процессорное время и сетевой канал бэкенда. К эндпоинту скачивания подключен `IMemoryCache`: 1. При первом запросе файла (например, аватара популярного пользователя), он скачивается из MinIO во временный файл ОС на бэкенде. 2. Файл прогоняется через `CryptoStream` (с использованием `IV` из метаданных корзины S3) для дешифровки и выгрузки в `MemoryStream`. 3. Байты готового файла, его `ContentType` и исходное имя кэшируются в RAM бэкенда на **30 минут** (Sliding Expiration). 4. Все последующие запросы отдают готовые байты прямо из оперативной памяти без сетевого похода в MinIO и без повторной расшифровки. ### Поддержка Range-запросов API использует метод `Results.File(..., enableRangeProcessing: true)`. Это означает, что плееры в браузере или мобильном клиенте могут запрашивать видео кусками (например, `Range: bytes=1000-2000`), и бэкенд корректно отдаст только нужный чанк (из кэша или после скачивания), что делает модуль пригодным для видео-стриминга прямо из коробки. --- ## Итог Модуль представляет собой пуленепробиваемый шлюз для работы с медиа: * Обеспечивает полную конфиденциальность (ни один файл не хранится открытым в корзине облака). * Защищен от дубликатов (переиспользование за счет SHA-256 хэшей). * Высоко оптимизирован для раздачи горячего контента (In-Memory кэширование и поддержка HTTP Range Streaming).