Работа с файлами в системе#

Документ описывает общую логику работы с файлами в системе: где и как они хранятся, какие объекты и API участвуют в их создании и использовании, как файл проходит путь от загрузки до сохранения в файловом хранилище.

Сначала описаны общая схема работы с файлами и основные сущности, затем подробно рассматриваются файловые хранилища, сервис прикреплённых файлов, объект Btk_File, файловое API и связанные механизмы.

Общая схема работы с файлами#

Файлы в системе не хранятся в базе данных. Для их хранения используются файловые хранилища, доступные серверам приложений как внешние ресурсы. В зависимости от конфигурации системы такие хранилища могут быть подключены к серверу приложений и использоваться как доступные ему локальные диски или иные внешние файловые ресурсы.

Работа с файлами в системе строится вокруг нескольких уровней:

  • файловые хранилища — определяют, где физически хранится файл;

  • файловое API — используется в коде для создания, записи, чтения и проверки файлов;

  • сервис прикреплённых файлов — связывает файл с объектом системы и определяет режим работы с прикреплёнными файлами. В его модели используются объекты Btk_Attach, Btk_AttachVer и Btk_AttachItem;

  • объект Btk_File — хранит метаинформацию о файле в базе данных.

Общая схема работы с файлом выглядит так:

  1. В коде или через пользовательский интерфейс инициируется операция работы с файлом. Это может быть прикрепление файла через интерфейс, а также вызов файлового API для создания, записи, чтения, скачивания, перемещения или удаления файла.

  2. Система определяет файловое хранилище, в которое должен быть записан файл.

  3. В базе данных создаётся запись о файле.

  4. Физическое содержимое файла записывается в файловое хранилище.

  5. Файл связывается с объектом системы через сервис прикреплённых файлов или другой механизм прикладной логики.

  6. При необходимости файл становится доступен пользователю через операции интерфейса и механизмы выдачи файлов, реализованные в системе.

Файловые хранилища#

База данных и файловое хранилище — это разные системы. Операция записи в базу данных и операция записи физического файла в файловое хранилище не образуют единую транзакцию.

Из-за этого в системе возможны ситуации рассинхрона, когда запись о файле в базе данных уже создана или удалена, а физический файл в файловом хранилище ещё существует или уже удалён.

Система использует справочник файловых хранилищ для классификации мест хранения файлов и для выбора конкретного хранилища при сохранении файла.

В системе реализованы следующие типы файловых хранилищ:

  • Локальное (FileStorageFileImpl) — использует файловый ресурс, доступный серверу приложений как локальный диск;

  • REST File Server (FileStorageRestImpl) — использует внешний файловый сервер, доступный по REST;

  • S3 протокол (S3FileStorageImpl) — использует объектное хранилище, доступное по протоколу S3.

Файловое хранилище в системе — это не только запись в справочнике, но и программная абстракция, через которую выполняются операции с физическими файлами. Для работы с физическим содержимым файла используются абстракции FileStorage и File, а также их реализации для разных типов файловых хранилищ, например локального хранилища, REST File Server и S3.

Настройка файловых хранилищ выполняется в приложении «Настройка системы» по пути Сущности > Файловые хранилища.

В системе должно быть настроено минимум два хранилища:

  • Default — хранилище по умолчанию;

  • btkAttach — хранилище прикреплённых файлов.

Распределение файлов по хранилищам#

При загрузке файла система определяет, в какое файловое хранилище его необходимо сохранить. Этот механизм работает по всей системе и используется для всех кнопок, форм и инструментов, связанных с добавлением файлов.

При работе с файлами система может определять файловое хранилище автоматически или использовать файловое хранилище, явно заданное в коде. Разработчик указывает системное имя файлового хранилища в файловом API.

Общая логика выбора файлового хранилища следующая:

  1. Сначала система проверяет настройки распределения файлов.

  2. Если поля, участвующие в распределении, не заполнены или по настройкам распределения не удалось определить подходящее файловое хранилище, используется файловое хранилище, указанное в файловом API.

  3. Если файловое хранилище не указано в файловом API, используется файловое хранилище, объявленное в системе как хранилище по умолчанию.

Настройки распределения задаются на вкладке «Распределение файлов по типам» в карточке файлового хранилища. Эта вкладка используется для первого этапа выбора файлового хранилища — по параметрам документа.

Для распределения используются параметры тип документа, тип файла, класс, подкласс и модуль. Параметр модуль определяется по принадлежности класса объекта-источника модулю Btk_Class.idModule. Каждое поле в настройке файлового хранилища может быть задано сразу для нескольких значений.

Поиск подходящего файлового хранилища по настройкам распределения выполняется последовательно, от более точного условия к более общему. Приоритет поиска следующий:

  1. тип документа + тип файла;

  2. тип документа;

  3. подкласс + тип файла

  4. подкласс

  5. класс + тип файла;

  6. класс;

  7. модуль + тип файла;

  8. модуль.

Примечание

Если по алгоритму найдено несколько подходящих файловых хранилищ, используется файловое хранилище с минимальным id. На практике это соответствует выбору хранилища, созданного раньше остальных.

Если документ перемещён вручную, chooseFileStorage(...) использует файловое хранилище, переданное в параметрах, либо btkAttach, если хранилище не передано. В остальных случаях файловое хранилище подбирается по настройкам распределения файлов по типам.

Если требуется новое файловое хранилище или новое место расположения файлов, можно создать новое файловое хранилище, задать в нём нужные параметры распределения и, при необходимости, использовать его в файловом API или назначить файловым хранилищем по умолчанию. После этого файлы будут помещаться в него автоматически в соответствии с заданной логикой выбора.

Принудительный выбор файлового хранилища#

Для сценариев, требующих сохранения файла в конкретное файловое хранилище независимо от стандартных правил распределения, в файловом API реализован метод для временного контекста withFileStorageContext. Он позволяет точечно задать целевое хранилище для определённого участка кода. Для этого необходимо передать идентификатор файлового хранилища в параметре idpFileStorage при вызове метода. Параметры применяются строго в пределах заданного блока и не влияют на остальные операции с файлами в системе.

Логика работы метода:

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

  • Выполняет переданный блок кода, в рамках которого все операции с файлами автоматически используют параметры контекста.

  • Автоматически сбрасывает параметры контекста в None после завершения блока.

В основе механизма лежит метод setFileStorageContext, который записывает переданные параметры в активный контекст. withFileStorageContext является безопасной обёрткой: он вызывает этот метод для установки значений перед выполнением блока и повторно — для их сброса в None по завершении.

Пример использования:

// Пример 1: Установка контекста
// Целевое хранилище задаётся в параметрах withFileStorageContext.
// Все операции с файлами внутри блока используют это хранилище, независимо от настроек распределения и явных параметров методов.
val idavFile = Btk_FileLib().withFileStorageContext(
  idpFileStorage = Wf_Lib().idFileStorageWf
) {
  Btk_FileLib().uploadFiles(
    idpFileStorage = idFileStorageWf, // - будет проигнорировано, если задано в контексте
    gidpSrc = gidpSrc,
    idpSrcObjectType = Btk_ObjectPkg().getIdObjectType(gidpSrc)
  )
}
// После выхода из блока контекст автоматически сбрасывается.
// Пример 2: Чтение контекста внутри chooseFileStorage
// Метод проверяет активный контекст и через .nvl() отдаёт приоритет его значениям
val jFSCtx = getFileStorageContext()
val idvFileStorage = jFSCtx.idFileStorage.nvl(Btk_FilePkg().chooseFileStorage( // - приоритет контекста
      idpAttachFileType = jFSCtx.idAttachFileType.nvl(idpAttachFileType),
      idpSrcObjectType = jFSCtx.idSrcObjectType.nvl(idpSrcObjectType),
      gidpSrc = jFSCtx.gidSrc.nvl(gidpSrc),
      idpFileStorage = idpFileStorage,
      idpClassDoc = jFSCtx.idClassDoc.nvl(idpClassDoc),
      bpManualMoved = bpManualMoved,
      bpTemp = bpTemp)
)
// Если idpFileStorage задан в контексте, метод вернёт именно его, игнорируя значение, переданное в явном аргументе.
// chooseFileStorage не будет выполняться при наличии в контексте idpFileStorage.

Примечание

Контекст следует применять только для точечных сценариев, где требуется гарантированное сохранение файла в заданном хранилище. Для регулярного управления маршрутизацией файлов рекомендуется использовать справочник настроек распределения.

Настройка очистки хранилища от устаревших файлов#

Для очистки устаревших файлов в системе используется настройка Btk_FileStorageCleanSetting. Она поддерживает два варианта работы:

  • удаление файла из хранилища;

  • перемещение файла в указанное файловое хранилище, используемое как архив.

При удалении через Btk_FileStorageCleanSetting запись Btk_File не удаляется. Физический файл удаляется из хранилища, а Btk_File помечается как удалённый признаком bDeleted. Этот механизм применяется только к временным файлам, которые определяются по типу вложения на закладке распределения файлов по типам.

Для настройки очистки файлового хранилища используется вкладка «Настройка очистки хранилища от устаревших файлов».

На вкладке можно задать:

  • Срок хранения в днях — количество дней, в течение которых файл хранится в хранилище с момента загрузки;

  • Действие — действие, которое применяется при очистке хранилища. Возможны два варианта: Удалить или Переместить;

  • Хранилище для перемещения — файловое хранилище, в которое перемещается файл, если выбрано действие Переместить;

  • Тип вложения — тип прикреплённых файлов, для которых применяется указанное действие.

Администрирование файловых хранилищ#

Для контроля содержимого файловых хранилищ и выполнения операций с файлами используется раздел «Администрирование файловых хранилищ».

Раздел находится в приложении «Настройки системы» по пути Сущности > Администрирование файловых хранилищ.

В левой части окна отображается список файловых хранилищ системы. При выборе файлового хранилища открывается список файлов, которые в нём находятся.

Для каждого файла отображаются:

  • имя файла;

  • тип объекта-источника;

  • объект-источник;

  • тип прикреплённого файла;

  • создатель;

  • дата создания;

  • наличие вложений;

  • размер.

В списке файлов доступны следующие операции:

  • Удалить — удаляет выбранный файл;

  • Открыть карточку объекта-источника — открывает карточку объекта, с которым связан файл;

  • Переместить в другое хранилище — перемещает выбранный файл в другое файловое хранилище.

Для выбранного файлового хранилища в меню «Дополнительно» доступны следующие операции:

  • Запуск задания по удалению/перемещению по расписанию — вручную запускает процедуру очистки, настроенную на вкладке «Настройка очистки хранилища от устаревших файлов»;

  • Отчёт по планируемому удалению — открывает отчёт со списком файлов, которые будут перемещены или удалены при следующей очистке.

Чтобы операции «Запуск задания по удалению/перемещению по расписанию» и «Отчёт по планируемому удалению» были доступны, в менеджере заданий должно быть активно задание «Актуализация расположения файлов в файловых хранилищах».

Сервис прикреплённых файлов#

Сервис прикреплённых файлов отвечает за прикрепление файлов к объектам системы и за режим работы с прикреплёнными файлами.

Сервис прикреплённых файлов позволяет прикреплять к объектам класса произвольные файлы, которые сохраняются в файловом хранилище и сопоставляются с конечным объектом-владельцем.

Сервис прикрепления файлов определяет, как выполняется работа с прикреплёнными файлами. Режим работы сервиса определяет, сохраняется ли история изменений файла.

Для минимизации объёма хранилища используется алгоритм, позволяющий нескольким объектам ссылаться на один физический файл:

  • файл загружается в хранилище только один раз;

  • при копировании объектов создаётся символическая ссылка через btk_attachitem, а не физическая копия.

При создании прикреплённого файла формируются следующие объекты:

  • Btk_File — центральный объект, в котором хранится метаинформация о файле в базе данных. Физическое содержимое файла хранится не в самом Btk_File, а в файловом хранилище. Объект Btk_File связывает запись о файле в базе данных с его физическим хранением.

  • Btk_Attach — объект прикреплённого файла. Он относится к сервису прикреплённых файлов, хранит данные о прикреплённом файле и используется в логике отображения файла пользователю и работы сервиса прикреплённых файлов.

  • Btk_AttachVer — объект версии прикреплённого файла. Он ссылается на Btk_Attach и содержит ссылку на Btk_File, то есть на запись о физическом файле. Если для сервиса прикрепления файлов включена версионность, при каждом изменении файла создаётся новая запись Btk_AttachVer.

  • Btk_AttachItem — объект связи, который связывает прикреплённый файл Btk_Attach с объектом системы.

Таким образом, при загрузке файла в системе создаётся не одна запись, а набор связанных объектов. Btk_File отвечает за хранение сведений о физическом файле и его связи с файловым хранилищем, Btk_Attach представляет файл в сервисе прикреплённых файлов, Btk_AttachVer отвечает за версионность, а Btk_AttachItem связывает прикреплённый файл с объектом системы.

В режиме simple для прикреплённого файла всегда хранится одна версия. В режиме versioned при каждом изменении создаётся новая запись Btk_AttachVer.

Настройка сервиса прикрепления файлов#

По умолчанию сервис прикреплённых файлов для класса отключён. Для его подключения и выбора режима работы в ODM-файле класса указывается тип хранения:

<class xmlns="http://www.global-system.ru/xsd/global3-class-1.0"
       name="Gds_ControlDoc"
       caption="Документ контроля"
       cardEditor.representation="Card"
       listEditor.representation="List"
       viewOptions.openCardType="mdi"
       supertype="document"
       attachType="versioned"/>

Параметр attachType определяет режим работы сервиса прикрепления файлов для класса:

  • simple — простое хранение;

  • versioned — версионное хранение.

После генерации AVM-файла во все отображения (Card, List, Tree) автоматически добавляется закладка «Прикреплённые файлы».

Режимы работы сервиса прикрепления файлов#

Для сервиса прикрепления файлов (Attach) поддерживаются два режима работы:

  • простой;

  • версионный.

Режим работы настраивается не для конкретного файлового хранилища, а для сервиса прикрепления файлов у класса. Одно файловое хранилище может содержать файлы с разными режимами хранения. Это связано с тем, что файловое хранилище выбирается по правилам распределения, а режим работы с прикреплёнными файлами настраивается отдельно — на уровне сервиса прикрепления файлов (Attach).

Простое хранение файлов#

Простое хранение — это режим работы сервиса прикрепления файлов (Attach) без хранения истории изменений. Это частный случай версионного хранения с одной версией: любое изменение приводит к перезаписи файла.

Доступные операции:

  • Прикрепить файл — в хранилище добавляется новый файл, в закладке отображается запись с флагом «Основной».

  • Удаление — удаляется запись из закладки. Если запись отмечена как основная, файл удаляется из хранилища.

    Внимание

    Операция удаления записи из хранилища необратима.

  • Скачать файл — из хранилища скачивается файл с именем и расширением, указанными в записи.

  • Сделать файл основным — устанавливается флаг «Основной». У предыдущей основной записи флаг снимается.

При копировании родительской записи копируются и записи прикреплённых файлов, но без флага «Основной».

Версионное хранение файлов#

Версионное хранение — это режим работы сервиса прикрепления файлов (Attach), при котором сохраняется история изменений. Любое изменение файла создаёт новую версию.

Доступны все операции простого хранения, а также:

  • Добавить новую версию — к записи добавляется версия; предыдущие сохраняются.

  • Удалить последнюю версию — удаляется последняя версия. Если версия одна, предлагается удалить всю запись.

    Внимание

    Операция удаления записи из хранилища необратима.

  • Отобразить историю изменений — открывается список версий. Для каждой доступны операции скачивания и удаления.

При копировании родительской записи по умолчанию копируются и записи Btk_Attach. Вместе с ними копируются прикреплённые файлы, а для версионного хранения — все версии файла. Флаг «Основной» при этом не переносится.

Основные сценарии работы с файлами#

В системе с файлами выполняются три основных сценария:

  • загрузка файла;

  • просмотр, скачивание и получение файла для редактирования;

  • удаление файла.

Загрузка файла#

Загрузка файла через кнопку загрузки в сервисе прикреплённых файлов выполняется следующим образом:

  1. Пользователь нажимает кнопку загрузки файла в закладке «Прикреплённые файлы».

  2. Система получает файл и через файловое API определяет файловое хранилище, в которое его нужно сохранить.

  3. В базе данных создаётся запись Btk_File, в которой сохраняется метаинформация о файле.

  4. Для файла формируется полное имя и контекст хранения.

  5. Содержимое файла записывается в файловое хранилище.

  6. После записи файла создаются и связываются объекты сервиса прикреплённых файлов.

При загрузке прикреплённого файла формируются следующие объекты:

  • Btk_File — центральный объект, в котором хранится метаинформация о файле в базе данных. Физическое содержимое файла хранится не в самом Btk_File, а в файловом хранилище. Объект Btk_File связывает запись о файле в базе данных с его физическим хранением;

  • Btk_Attach — объект прикреплённого файла. Он относится к сервису прикреплённых файлов, хранит данные о прикреплённом файле и используется в логике отображения файла пользователю и работы сервиса прикреплённых файлов;

  • Btk_AttachVer — объект версии прикреплённого файла. Он ссылается на Btk_Attach и содержит ссылку на Btk_File, то есть на запись о физическом файле. Если для сервиса прикрепления файлов включена версионность, при каждом изменении файла создаётся новая запись Btk_AttachVer;

  • Btk_AttachItem — объект связи, который связывает прикреплённый файл Btk_Attach с объектом системы.

Таким образом, при загрузке файла через сервис прикреплённых файлов в системе создаётся не одна запись, а набор связанных объектов. Btk_File отвечает за хранение сведений о физическом файле и его связи с файловым хранилищем, Btk_Attach представляет файл в сервисе прикреплённых файлов, Btk_AttachVer отвечает за версионность, а Btk_AttachItem связывает прикреплённый файл с объектом системы.

В режиме simple для прикреплённого файла всегда хранится одна версия. В режиме versioned при каждом изменении создаётся новая запись Btk_AttachVer.

Ограничения на размер и формат файлов#

В системе можно настроить ограничения на размер и формат файлов. Эти ограничения используются для контроля загрузки файлов в файловое хранилище и получения файлов из него.

По умолчанию оба ограничения выключены.

Настройка ограничений выполняется в приложении «Настройка приложения» по пути Настройки и сервисы > Настройка модулей системы > Общие настройки модулей > Btk > Файлы.

Доступны следующие настройки:

  • Ограничение расширений загружаемых файлов — определяет ограничения на загрузку файлов по их расширению;

  • Ограничение размера загружаемых файлов — определяет максимально допустимый размер загружаемого файла.

Ограничения применяются только при загрузке файла в файловое хранилище и при получении файла из него. Если файл создаётся в прикладном коде и затем записывается в файловое хранилище, ограничения также применяются. Если файл формируется и используется внутри системы без загрузки в файловое хранилище, эти ограничения не срабатывают.

Для отдельных классов файлов можно настроить исключения из этих ограничений. Исключения задаются в классе Btk_FileRestrictionDisable по пути Сущности > Классы > Btk_FileRestrictionDisable.

Исключение настраивается для класса файла. Поддерживаются два варианта отключения ограничений:

  • Полное отключение — ограничения для указанного класса не применяются;

  • Отключение по скрипту — ограничения отключаются только при выполнении условий, заданных в процедуре.

При настройке отключения по скрипту можно указать процедуру, которая определяет, должно ли применяться исключение для конкретного файла.

Ограничения по размеру файлов особенно важны, потому что при работе с файлами система загружает файл в память целиком. Обработка файлов как потоков не используется.

При работе с файлами большого размера это может привести к исчерпанию памяти, превышению доступного лимита памяти и аварийному завершению работы приложения. Чтобы снизить этот риск, рекомендуется настраивать ограничения на размер загружаемых файлов.

Просмотр, скачивание и получение файлов для редактирования#

Для просмотра, скачивания и получения файлов для редактирования используется REST-пакет Btk_FileRestPkg.

Btk_FileRestPkg обеспечивает получение файлов из системы через REST-запросы. С его помощью можно решать следующие задачи:

  • открыть файл для просмотра;

  • скачать файл;

  • получить файл для последующего редактирования;

  • создать файл в указанном файловом хранилище через REST-запрос.

Btk_FileRestPkg используется:

  • для предпросмотра документов — getFileForView();

  • для скачивания — getFileForDownload();

  • для получения файла для редактирования — getFileForUpdate().

Для вызова методов Btk_FileRestPkg формируется REST-запрос, в который передаётся параметр ID_FILE с идентификатором файла. Например, для получения файла для редактирования может использоваться запрос:

/app/sys/rest/ss/pkg/Btk_FileRestPkg/getFileForUpdate?ID_FILE=28252

Этот пакет не связан напрямую с attach. Он взаимодействует с Btk_File и файловым хранилищем.

Удаление файла#

Удаление файла в системе может происходить как при удалении объекта, к которому файл прикреплён, так и при удалении файла из сервиса прикреплённых файлов. При удалении затрагиваются связанные записи в базе данных и физический файл в файловом хранилище.

Если файл используется в сервисе прикреплённых файлов, удаление выполняется через связанные объекты этой модели: Btk_AttachItem, Btk_Attach, Btk_AttachVer и Btk_File.

При удалении документа с attach:

  • удаляются его связи с attach через Btk_AttachItem;

  • если attach отмечен как основной (bMain = 1), удаляются все Btk_AttachItem, ссылающиеся на этот attach, и сам Btk_Attach;

  • при удалении Btk_Attach также удаляются его версии;

  • при удалении версий затрагиваются связанные записи Btk_File;

  • для файлов Btk_File, указанных в версиях, планируется удаление перед flush;

  • если Btk_Attach имеет подписанные версии, его удаление запрещено.

Удаление физического файла из файлового хранилища происходит только при удалении Btk_File или при установке у него флага bDeleted, если в прикладной логике не указано иное.

При удалении Btk_File запрос на удаление файла из файлового хранилища отправляется перед flush в базу данных.

В сценарии с attach удаление выполняется не напрямую по физическому файлу, а через цепочку связанных объектов. В результате удаляется не только физический файл, но и связанная с ним запись Btk_File в базе данных.

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

Файловое API#

Для программной работы с файлами в системе используется файловое API. Оно применяется для создания записи Btk_File, выбора файлового хранилища, записи и чтения содержимого файла, а также для удаления или перемещения файлов.

Один из примеров использования файлового API — сохранение файла в системе с одновременным созданием записи Btk_File.

Например, если система уже получила входной поток файла, файл можно сохранить следующим образом:

val idFile = Btk_FilePkg().createAndFill(
    "test.pdf",
    inputStream
)

В этом сценарии файловое API:

  • создаёт запись Btk_File;

  • определяет файловое хранилище;

  • записывает физическое содержимое файла в файловое хранилище.

К основным компонентам файлового API относятся:

  • Btk_FileApi — API для работы с объектом Btk_File и его содержимым;

  • Btk_FileStorageApi — API для работы с файловыми хранилищами;

  • Btk_FileStorageTypeApi — API для работы с типами файловых хранилищ;

  • Btk_FilePkg — пакет с основной логикой работы с файлами: созданием записи Btk_File, записью содержимого файла, выбором файлового хранилища и вспомогательными операциями.

Ниже описаны основные методы и служебные элементы файлового API, которые используются при создании, чтении, перемещении и удалении файлов.

Основные методы создания и записи файла#

Для работы с файлами в системе используется пакет Btk_FilePkg. В нём реализованы следующие основные методы создания и записи файла:

  • createFile(...) — создаёт запись Btk_File и заполняет её метаданные;

  • fill(...) — записывает содержимое в уже существующую запись файла;

  • createAndFill(...) — создаёт запись Btk_File и сразу записывает в неё содержимое файла;

  • createFileWithContent(...) — выполняет ту же операцию, что и createAndFill(...), но автоматически закрывает переданный поток.

Такое разделение нужно, потому что в системе создание записи Btk_File и запись физического содержимого файла — это разные операции.

Раздельное использование createFile(...) и fill(...) применяется в случаях, когда файл обрабатывается в несколько этапов. Например:

  • сначала нужно создать запись Btk_File, определить файловое хранилище и получить идентификатор файла;

  • затем связать этот файл с другими объектами системы;

  • после этого отдельным шагом записать физическое содержимое файла.

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

Метод fill(...) также можно использовать для перезаписи содержимого уже существующего файла. Например:

def updateFile(idpFile: NLong, bytes: Array[Byte]): Unit = {
    Btk_FilePkg().fill(idpFile, bytes)
}

createAndFill(...) используется в сценариях, когда запись Btk_File и физическое содержимое файла можно создать за один вызов.

Этот метод удобно применять, если файл сразу готов к сохранению. Если же система сначала создаёт запись о файле, связывает её с другими объектами, а затем получает поток данных для записи, используются createFile(...) и fill(...) по отдельности.

Выбор файлового хранилища#

В файловом API выбор файлового хранилища выполняется методом chooseFileStorage(...) из пакета Btk_FilePkg.

Метод используется во внутренней логике файлового API и вызывается в сценариях, где системе нужно определить, в какое файловое хранилище сохранить или переместить файл. В частности, он применяется в методах создания и записи файла, например createFile(...) и createAndFill(...).

В метод передаются следующие параметры:

  • idpAttachFileType — тип прикрепляемого файла;

  • idpSrcObjectType — тип объекта-источника;

  • idpFileStorage — файловое хранилище, переданное явно; используется при ручном перемещении файла;

  • idpClassDoc — класс документа или объекта, для которого определяется файловое хранилище;

  • bpManualMoved — признак ручного перемещения файла. Если признак активен, используется файловое хранилище, переданное в idpFileStorage, а если оно не передано — файловое хранилище btkAttach;

  • bpTemp — признак временного файла, который участвует в логике выбора файлового хранилища.

Мастер-объект может отличаться от объекта-источника, поэтому при выборе файлового хранилища учитываются параметры как самого файла, так и объекта, с которым он связан.

Пример использования в коде:

val idFileStorage = Btk_FilePkg().chooseFileStorage(
    idpAttachFileType = idAttachType,
    idpSrcObjectType = idSrcObjectType,
    idpFileStorage = idStorage,
    idpClassDoc = idClassDoc,
    bpManualMoved = false,
    bpTemp = false
)

На практике этот метод обычно не вызывают отдельно в прикладной логике, а используют через более высокоуровневые методы файлового API, которые сами определяют файловое хранилище в процессе создания или записи файла.

Перемещение и удаление файлов#

В файловом API предусмотрены методы для перемещения и удаления файлов.

Для перемещения файлов используются:

  • autoMove() — автоматически перемещает файл в другое файловое хранилище в рамках внутренней логики системы. Этот метод применяется, если при изменении данных о файле, например типа прикрепления или типа объекта-источника, для файла должно использоваться другое файловое хранилище. Метод используется только в тех случаях, когда перемещение не считается ручным.

  • manualMove() — перемещает файл в другое файловое хранилище по явному действию пользователя и устанавливает признак, что файл был перемещён вручную. Этот метод используется в интерфейсе «Администрирование файловых хранилищ».

Разница между методами заключается в назначении:

  • autoMove() используется для автоматического перемещения файла по внутренним правилам системы;

  • manualMove() используется в сценариях, когда пользователь сам выбирает, в какое файловое хранилище нужно переместить файл.

Пример вызова manualMove():

val ropFile = Btk_FileApi().load(idpFile)
val idNewStorage = Btk_FileStorageApi().findByMnemoCode("customStorage")
Btk_FileApi().manualMove(ropFile, ropFile.get(_.idFileStorage), idNewStorage)

Пример для autoMove() будет аналогичным.

Для удаления файла используются:

  • Btk_FileApi().delete() — удаляет объект Btk_File из базы данных. Перед вызовом этого метода необходимо удалить все ссылки, в которых используется данный файл. Физический файл при этом также удаляется из файлового хранилища.

  • Btk_FileApi.setbDeleted() — устанавливает у объекта Btk_File признак удаления bDeleted. Сам объект Btk_File при этом сохраняется в базе данных, а физический файл удаляется из файлового хранилища.

Пример полного удаления объекта Btk_File:

val ropFile = Btk_FileApi().load(idpFile)
Btk_FileApi().delete(ropFile)

Файловый контекст#

При работе с файлом файловое API использует служебный объект — файловый контекст. Он содержит дополнительные данные, которые используются при обработке файла, выборе файлового хранилища и выполнении связанной логики, например при проверке ограничений на загрузку файлов.

Файловый контекст представляет собой case class со следующими полями:

  • gidpSrc — источник;

  • spExt — расширение;

  • params — карта параметров [String, Any].

Файловый контекст используется в случаях, когда при обработке файла системе нужно передать не только сам файл, но и дополнительную информацию о нём.
Например, через файловый контекст можно передать расширение файла, идентификатор объекта-источника или дополнительные параметры, которые участвуют в выборе файлового хранилища и проверке допустимости загрузки файла.

Поле params позволяет передавать в файловое API дополнительные параметры, которые не входят в фиксированный набор полей файлового контекста.

Вставка изображений в прикреплённые файлы типов Word и PDF#

Для вставки изображений в прикрепляемые файлы документа настройте нужные изображения в коллекции-расширении «Настройки вставки изображений» для типа объекта этого документа.

В коллекции доступны следующие настройки:

  • Активность — определяет, будет ли изображение вставлено в прикреплённый файл.

  • Печатная форма — указывается форма типа Jasper с форматом PNG. Передаётся один аргумент: IDDOC (ID документа).

  • Изображение — файл в формате PNG.

    Примечание

    Если указана печатная форма, файл изображения удаляется. При загрузке изображения ссылка на печатную форму удаляется.

  • Положение изображения по осям X, Y — определяет координаты. Точка отсчёта — нижний левый угол документа.

  • Ширина и высота изображения — задают размер вставляемого изображения.

Как только в коллекции появится активное изображение, в отображении прикреплённых файлов для документов данного типа становятся доступны операции:

  • вставка изображения в один документ;

  • вставка изображения во все документы сразу.