Идеология SbisFile/attach

В нашем продукте есть множество сервисов, которые требуют постобработки данных после загрузки файла (далее по тексту "ресурс"). Также у нас используются различные механизмы получения ресурсов и их загрузок на сервер. Например, выбор файла через диалоговое окно из файловой системы или скан документа прямо со сканера.

Для этого мы разделили решение на компоненты:

  • Ресурсы — интерфейс IResource;
  • Способ выбора ресурсов — интерфейс IResourceGetter;
  • Загрузка ресурсов на удалённые сервисы. Для этого взяли обобщенный интерфейс общения с сервисами — ISource;
  • Центральный компонент — SbisFile/attach:default, который связывает все компоненты вместе.

ISource

Компоненты, реализующие данный интерфейс, предназначены для загрузки ресурсов на удалённый сервис.

Через браузер

  1. SbisFile/Source/BL — в метод бизнес-логики;
  2. SbisFile/Source/SbisDisk — в СБИС Диск;
  3. SbisFile/Source/FileTransfer — на сервис временных файлов;
  4. SbisFile/Source/FileStorage — в FileStorage.

Через СБИС Плагин

  1. SBIS3.Plugin/Integration/Source/BL — в метод бизнес-логики;
  2. SBIS3.Plugin/Integration/Source/SBISDisk — в СБИС Диск;
  3. SBIS3.Plugin/Integration/Source/FileTransfer — в FileTransfer;
  4. SBIS3.Plugin/Integration/Source/FileStorage — в FileStorage.

IResource

Интерфейс ресурса. Позволяет указать, какой компонент ISource использовать.

На данный момент существует три типа ресурсов:

  1. LocalFile — содержит внутри бинарный объект Blob, который мы можем загрузить через браузер;
  2. LocalFileLink — содержит внутри строку с путем до файла в файловой системе ПК. Такой тип ресурса можно загрузить только через СБИС Плагин;
  3. HttpFileLink — содержит внутри строку с путем до ресурса в интернете. Пока способ загрузки не найден.

Через СБИС Плагин невозможно загрузить файлы, если уже загружен Blob. Через браузер невозможно загрузить файлы, если путь до этих фалов есть в системе.

IResourceGetter

Интерфейс получения ресурса типа IResource.

На данный момент существуют следующие компоненты данного типа для получения ресурсов.

Возвращают LocalFile

  • SbisFile/attach:option.getter.Dialogs — для выбора файла через окно выбора файла СБИС Плагина;
  • SbisFile/attach:option.getter.Scanner — для сканирования файла с помощью СБИС Плагина;
  • SbisFile/attach:option.getter.Clipboard — для получения файла из буфера обмена с помощью СБИС Плагина;
  • SbisFile/attach:option.getter.FileChooser — панель выбора файлов, сделанная на DOM-элементах с отображением имен из файлов отчетности (xml).

SbisFile/attach:default

Компонент SbisFile/attach:default создан для того, чтобы можно было описать способ загрузки данных в сервис (например, в СБИС Диск) и организовать их постобработку. А затем передать настроенный SbisFile/attach:default в конкретную прикладную область для его использования.

Если посмотреть на список компонентов, которые получают и загружают ресурсы, можно заметить, что не каждый ресурс можно загрузить через браузер и через СБИС Плагин.

Разработчик, который подготавливает SbisFile/attach:default, регистрирует все возможные ISource для загрузки в необходимый сервис для всех типов ресурсов, которые будут загружены, только планируются для загрузки или, в принципе, уже могут быть загружены.

После этого с помощью событий регистрируется постобработка выбранных и загруженных ресурсов. Например, если сервис не поддерживает загрузку ресурсов более 10МБ, то на событие onChoose можно установить проверку. Либо по событию onLoaded вызвать метод БЛ для привязки ресурса к объекту.

choose(getterType: string): Promise<(IResource | Error)[]>

При вызове choose() выбирается IResourceGetter, зарегистрированный в SbisFile/attach:default по имени. Получить тип геттера можно, вызвав getter.getType().

upload(meta: object): Promise<<File/attach:Model>[]>

При вызове upload() происходит выбор соответствующего ISource по установленному ресурсу в SbisFile/attach:default. Затем вызывается метод ISource::create(meta).

Схема последовательности загрузки

Ленивая загрузка

В основном, не нужно грузить код, который выбирает и загружает файлы при открытии страницы. Поэтому мы сделали возможность ленивой загрузки этих компонентов. Для того чтобы лениво подгружать код, необходимо передать опции (легкие и простые классы, содержащие 2 строчки), в которых описано, какой интерфейс загружать — IResourceGetter или ISource, и какие опции передавать им в конструктор. Как только будет вызван choose() или upload() класса SbisFile/attach:default, лениво загрузится геттер или ISource соответственно.

Это предпочтительный способ регистрации IResourceGetter и ISource.

Фабрика ISource

В некоторых случаях встречаются дублирующие способы загрузки ресурсов в один и тот же сервис. Например, загрузка файла в метод БЛ доступна и через браузер, и через СБИС Плагин. Для более удобного получения этих опций можно использовать фабрику опций - SbisFile/attach:option.source.Fabric.

Работа с SbisFile/attach:default

В идеале, команды, которые предоставляют какой-то сервис загрузки, предоставляют, также, настроенный SbisFile/attach:default для работы со своим сервисом. Прикладной разработчик настраивает SbisFile/attach:default и передает его в компонент, который предоставляет широкий визуальный способ выбора ресурсов (например, attachTo).

Подготовка загрузчика

Пример подготовки загрузчика для загрузки в метод БЛ с постобработкой.

import Attach, { option } from 'SbisFile/attach';
// File/ResourceGetter/dropArea -единственный ResourceGetter, который должен грузиться энергично
import { Option as FileSystem } from 'File/ResourceGetter/dropArea';

const sourceCfg = {
   endpoint: { contract: "simple" },
   binding: { create: "ЗагрузитьВНикуда" },
   fileProperty: "Файл"
};
const getterCfg = {
   multiSelect: true,
   extensions: ["image"]
};
const attach = new Attach({
   // Возможные способы загрузки
   sourceOptions: [ // загрузка на бизнеслогику
      // для загрузки через XHR
      new option.source.BL(sourceCfg), 
      // для загрузки через СБИС Плагин
      new option.source.BLPlugin(sourceCfg) 
   ],
   // Возможные способы получения ресурсов
   // ResourceGetter'ы Плагина см SbisFile/attach/option/getter
   getterOptions: [
      // Для нативного окна выбора файлов
      new FileSystem(getterCfg),
      // Для выбора через Плагин
      new option.getter.FileChooser(getterCfg),
      // Для работы со сканерами
      new option.getter.Scanner(), 
      // Для получения фото с веб-камеры
      new option.getter.PhotoCam(),
      // Для получения ресурсов из буфера обмена
      new option.getter.Clipboard(),
      // Для выбора файлов через окно СБИС Плагин'a
      new option.getter.Dialogs() 
   ],
   multiSelect: true
});

attach.choose(FileSystem.getType()).then((results: IChooseResourceResult[]) => {
   // Результаты выбора файлов <IResource | Error>[]
   return attach.upload({
         // Дополнительные мета-данные для отправки
         // Сигнатура зависит от конечного сервиса загрузки
   });
}).then((models: Model[]) => {
// Результаты загрузки <File/attach:Model>[]
}).catch(console.error); // обязательный обработчик ошибки выбора/загрузки файлов

Использование загрузчика

attach.choose(Scanner.getType()).then(function(resources) {
   attach.upload().then(function(results) {
      results.every(function (response) {
         if (response instanceof Error) {
            console.error("Ошибказагрузкифайла", response);
         }

         // Прикладная логика.
      });
   });
}).catch(function (err) {
   console.log("Неполучилосьвыбратьфайлсосканера:", err);
});