filesDirectory.md 9.6 KB

FilesDirectoryService

Назначение

Сервис отвечает за хранение и раздачу файлов/медиа, валидацию категорий и параметров, а также за сценарии «отложенной загрузки» через резервирование токенов (для загрузки файлов от 1С). Предоставляет низкоуровневые операции (пути/метаданные/удаление) и высокоуровневые (загрузка, резервирование, превью по конфигу).

Публичные методы

Пути/файлы/метаданные

  • GetFilePath(fileId): string - получить физический путь хранения.
  • DeleteFile(fileId): void - удалить файл.
  • ValidExistFile(fileId): bool - проверить существование файла.
  • GetFileInfo(fileId): FileDescriptor - базовая информация по файлу.
  • GetFileInfoByHashAndCategory(hash, category): FileDescriptor - получить файл по хэшу и категории (для дедупликации).
  • GetFileConfig(category): FileImageConfig - конфигурация обработки/хранения для категории.

Загрузка

  • UploadFile(category, stream): FileDescriptor - загрузить файл в указанную категорию, вернуть дескриптор.
  • ValidExistFileAndCategoryAsync(filesIds, category): bool - проверить, что все файлы существуют и принадлежат категории.

Резервирование и отложенная загрузка

  • ReserveUploadFilesAsync(reserves[]): FileUploadReserve[] - зарезервировать параметры будущих файлов и выдать токены/идентификаторы резерва.
  • QueryReservedFileAsync(reserveIds[]): FileDescriptor?[] - узнать, загружен ли файл по резервации.
  • UploadReservedFileAsync(reserveTokenId, stream): FileDescriptor - загрузить файл по ранее выданному токену.

Конфигурация сервиса

Модель конфигурации

  • FilesServiceConfig - корневые параметры: каталог хранилища и массив конфигов по категориям.
  • FileImageConfig - правила обработки по категории: JPEG-качество, лимиты размеров/веса, ресайзы, набор превью, MIME, доступы. Также может содержать вложенные Previews - каскад настроек для генерации производных изображений.

Ключевые поля FileImageConfig:

  • Quality - качество изображения при сохранении;
  • ResizeToWidth / ResizeToHeight / MaxSideSize / ResizeToWH - правила изменения размеров (с приоритетами);
  • MaxFileSize - ограничение размера исходного файла;
  • Directory - подкаталог хранения для категории;
  • Mime - ожидаемый MIME тип;
  • Previews[] - список правил для генерации превью;
  • Accesses[] - список доступов, которым разрешена работа с категорией (если используется контроль доступа на уровне медиа).

Пример конфигурации (фрагменты)

В config.json (приложен к коду, как пример) заданы категории Product, UserIcon, Brand, Article, ArticleTile, Review - каждая со своими лимитами, директориями и превью:

  • Product: MaxSideSize: 2048, превью 256/512, Mime: image/jpeg.
  • UserIcon: обрезка/ресайз до ResizeToWH: [512, 512].
  • Article и ArticleTile: с Accesses: [100] (пример ограничения по доступам).
  • Review: MaxSideSize: 1920 и превью 128x128. Корневой каталог хранилища - FilesStorageDirectory: "filesstorage".

Модели

FileDescriptor

string Id - идентификатор файла, он же название файла
string Hash - SHA256
string Category - категория файла
FileTypeEnum Type - тип файла (пока используется только Image = 1)
string Mime 
DateTime Created
string Attributes - дополнительная информация о файле 

FileUploadReserve

Модель резервации: ReserveId, TokenId (для последующей загрузки), Category, FileId (заполняется, если файл уже загружен).

Используется для отложенной загрузки файла от мастер-системы.

Типовые потоки

[DirectoryService]   --v
                       
[Connector1CService] -> [FilesDirectoryService] -> [Static Files] <- [nginx] <-> PWA
  ^
[1C]                 --^  

Получения файла

Для получения файла нужно знать его категорию и его Id. Балансировочный сервер настраивается на доступ к физическим файлам по ссылке (корневой каталог, который указан в конфиге)/(Название категории)/(ID файла). Таким образом можно обращаться напрямую к статике минуя сервисы.

Прямая загрузка

  1. Клиент (обычно админская PWA) выбирает категорию → 2) вызывает UploadFile(category, stream) → 3) сервис валидирует MIME/размер/правила категории, применяет ресайз/качество, создаёт превью → 4) возвращает FileDescriptor (ID, MIME, Category и т. д.).

Отложенная загрузка (резервирование)

  1. Сервис/Пользователь запрашивает токен через ReserveUploadFilesAsync
  2. Позже, когда есть возможность, выполняется UploadReservedFileAsync(token, stream);
  3. Статус можно опрашивать через QueryReservedFileAsync(reserveIds);
  4. После успешной загрузки FileId становится доступным в модели резерва и можно его обновить у инициатора.

Так Directory синхронизируя данные с мастер системой, может зарезервировать файлы на загрузку. В качестве TokenId указывается Id файла из мастер системы. Данные о товарах загружаются большим скопом и быстро, а файлы загружаются долго. Поэтому приходится резервировать место для файлов, чтобы мастер система могла потом сама загрузить нужные файлы в FilesDirectory, когда будет возможность. Directory по заданию опрашивает FilesDirectory на предмет загрузки зарезервированных файлов, и обновляет информацию у себя.


Валидация, инварианты и безопасность

  • Соответствие категории: операции ValidExistFileAndCategoryAsync и GetFileInfoByHashAndCategory защищают от подмены категории/хэша и ошибок склейки.
  • Лимиты и преобразования: применяются по FileImageConfig с приоритетами правил ресайза (ширина → высота → max side → точный WH).
  • Доступы к категориям: при наличии Accesses[] доступ ограничивается доступами/ролями (пример - статьи/тайлы). Это позволяет хранить служебные медиа, недоступные обычным пользователям.
  • Дедупликация: поиск по Hash + Category позволяет повторно использовать уже загруженный файл.

Если нужно, оформлю это как отдельный раздел в документе и добавлю таблицу категорий из config.json (категория → директория → лимиты → превью → доступы).

DB

Содержит таблицы и индексы

-- Migration 1

files (
    Id TEXT PRIMARY KEY NOT NULL, 
    Category TEXT NOT NULL DEFAULT '',
    Path TEXT NOT NULL DEFAULT '', -- физический путь к файлу
    Hash TEXT NOT NULL DEFAULT '',
    Type INTEGER,
    Mime TEXT NOT NULL DEFAULT '',
    Created NUMBER,
    CreatorId NUMBER,
    Attributes TEXT);

reserves (
    ReserveId INTEGER PRIMARY KEY AUTOINCREMENT,
    TokenId TEXT NOT NULL DEFAULT '',
    Category TEXT NOT NULL DEFAULT '',
    FileId TEXT NOT NULL DEFAULT '');

INDEX files_hash on files (hash);

Назад