Как прикрепить файл к документу до его сохранения в 1С:ITIL?

Программист 1С v8.3 (Управляемые формы) IT и автоматизация бизнеса
← На главную

При проектировании сложных интерфейсов, мастеров ввода данных или специализированных обработок (например, рабочего места диспетчера Service Desk в конфигурации 1С:ITIL) разработчики часто сталкиваются с жестким требованием заказчика: предусмотреть возможность добавления вложений на этапе заполнения данных, когда сам документ в базе еще не создан.

Стандартный механизм работы с присоединенными файлами в 1С (основанный на Библиотеке стандартных подсистем — БСП) устроен так, что любой файл должен иметь владельца. Владельцем выступает конкретная ссылка на документ в базе данных (например, элемент справочника ЗапросПрисоединенныеФайлы ссылается на документ Запрос). Пока кнопка «Создать» или «Записать» не нажата, у нового документа нет ссылки в базе данных — его физически не существует. Соответственно, стандартная кнопка добавления файлов выдаст ошибку, так как поле Владелец заполнить нечем.

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

Концепция и этапы реализации

Чтобы обойти системное ограничение отсутствия ссылки у нового документа, мы разделим процесс на три последовательных этапа:

  1. Буферизация метаданных на клиенте: Пользователь выбирает файлы на своем компьютере. Мы асинхронно загружаем их во временное хранилище и запоминаем адреса этих хранилищ вместе с именами файлов в специальной таблице на форме нашей обработки.
  2. Создание и запись документа: При нажатии на финальную кнопку создания документа («Оформить запрос», «Создать» и т.д.) мы в единой транзакции создаем объект документа, заполняем его реквизиты из обработки и записываем его в базу данных. В этот момент мы получаем заветную ссылку (Ссылка) на созданный документ.
  3. Связывание файлов через БСП: Используя полученную ссылку в качестве владельца, мы программно переносим файлы из временного хранилища в постоянную систему хранения файлов БСП с помощью стандартных методов конфигурации.

Рассмотрим по шагам, как реализовать этот алгоритм программно.

Шаг 1. Подготовка формы обработки

Для начала создадим на форме нашей обработки (или мастера создания запросов) реквизит типа ТаблицаЗначений с именем СписокВыбранныхФайлов. Эта таблица будет служить временным буфером для хранения информации о файлах, которые пользователь планирует прикрепить.

Добавим в эту таблицу следующие колонки:

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

Шаг 2. Интерактивный выбор и асинхронная загрузка файлов

Для добавления файлов на форму добавим команду и соответствующую ей кнопку «Прикрепить файлы». Нам необходимо использовать современные асинхронные методы платформы 1С для выбора файлов на стороне клиента и немедленной их отправки во временное хранилище.

Проанализируем программный код клиентских процедур:


&НаКлиенте
Процедура ПрикрепитьФайлы(Команда)
    
    // Настраиваем параметры диалога выбора файлов
    ПараметрыДиалога = Новый ПараметрыДиалогаПомещенияФайлов;
    ПараметрыДиалога.МножественныйВыбор = Истина;
    ПараметрыДиалога.Заголовок = "Выберите файлы для прикрепления к запросу";
    
    // Описываем обработчик оповещения, который сработает после выбора файлов пользователем
    Оповещение = Новый ОписаниеОповещения("ПослеВыбораИЗагрузкиФайлов", ЭтотОбъект);
    
    // Важнейший момент: привязываем загрузку к УникальномуИдентификатору формы.
    // Это гарантирует, что временное хранилище не очистится при промежуточных серверных вызовах.
    НачатьПомещениеФайловНаСервер(Оповещение, , ПараметрыДиалога, Истина, УникальныйИдентификатор);
    
КонецПроцедуры

&НаКлиенте
Процедура ПослеВыбораИЗагрузкиФайлов(Результат, ДополнительныеПараметры) Экспорт
    
    // Если пользователь закрыл диалог выбора без добавления файлов
    Если Результат = Неопределено Тогда
        Возврат;
    КонецЕсли;
    
    // Обрабатываем каждый успешно загруженный во временное хранилище файл
    Для Каждого ОписаниеФайла Из Результат Цикл
        
        НоваяСтрока = СписокВыбранныхФайлов.Добавить();
        НоваяСтрока.Адрес = ОписаниеФайла.Адрес;
        НоваяСтрока.ИмяФайла = ОписаниеФайла.Имя;
        
        // Получаем информацию о файле для корректной передачи в БСП
        ИнформацияОФайле = Новый Файл(ОписаниеФайла.Имя);
        НоваяСтрока.ИмяБезРасширения = ИнформацияОФайле.ИмяБезРасширения;
        // Отрезаем точку от расширения, так как БСП требует чистый формат расширения
        НоваяСтрока.Расширение = СтрЗаменить(ИнформацияОФайле.Расширение, ".", "");
        
    КонецЦикла;
    
КонецПроцедуры

Важное примечание: Обратите внимание на параметр УникальныйИдентификатор в методе НачатьПомещениеФайловНаСервер. Если его не передать, платформа удалит файлы из временного хранилища при первом же контекстном переходе с клиента на сервер (например, при валидации реквизитов формы). Передача идентификатора текущей управляемой формы «привязывает» время жизни временных файлов к открытому окну обработки.

Шаг 3. Создание документа и программный перенос файлов

Теперь рассмотрим ключевой шаг — обработку нажатия кнопки «Создать». При активации этого действия управление передается на сервер. Мы должны открыть транзакцию, создать и записать документ Запрос, а затем для каждой строчки нашей таблицы вызвать механизмы интеграции файлов БСП.

Ни в коем случае нельзя пытаться создавать элементы справочника присоединенных файлов напрямую через метод СоздатьЭлемент(). Подсистема работы с файлами БСП ведет сложный учет метаданных в служебных регистрах (таких как НаличиеФайлов и СведенияОФайлах), а также управляет размещением данных на дисковых томах или в СУБД в зависимости от настроек вашей системы 1С:ITIL. Любое прямое вмешательство приведет к потере целостности данных.

Выясним, как сделать это правильно, используя программный интерфейс общего модуля РаботаСФайлами:


&НаСервере
Функция СоздатьЗапросИПрикрепитьФайлыНаСервере() Экспорт
    
    // Начинаем транзакцию, чтобы гарантировать: если файлы не запишутся, документ также не должен быть создан
    НачатьТранзакцию();
    
    Попытка
        
        // 1. Создаем и заполняем документ "Запрос"
        НовыйЗапрос = Документы.Запрос.СоздатьДокумент();
        НовыйЗапрос.Дата = ТекущаяДата();
        
        // Заполняем реквизиты документа из реквизитов нашей обработки
        НовыйЗапрос.Инициатор = ИнициаторЗапроса;
        НовыйЗапрос.Описание = ОписаниеПроблемы;
        НовыйЗапрос.Услуга = ВыбраннаяУслуга;
        НовыйЗапрос.Срочность = СрочностьЗапроса;
        
        // Записываем документ для получения постоянной ссылки
        НовыйЗапрос.Записать(РежимЗаписиДокумента.Запись);
        СсылкаНаДокумент = НовыйЗапрос.Ссылка;
        
        // 2. Программный перенос файлов из временного хранилища в базу данных БСП
        Для Каждого СтрокаФайла Из СписокВыбранныхФайлов Цикл
            
            // Проверяем, действительно ли адрес во временном хранилище еще валиден
            Если ЭтоАдресВременногоХранилища(СтрокаФайла.Адрес) Тогда
                
                // Получаем стандартную структуру параметров для добавления нового файла в БСП
                ПараметрыФайла = РаботаСФайлами.ПараметрыДобавленияФайла();
                ПараметрыФайла.ВладелецФайлов = СсылкаНаДокумент;
                ПараметрыФайла.ИмяБезРасширения = СтрокаФайла.ИмяБезРасширения;
                ПараметрыФайла.РасширениеБезТочки = СтрокаФайла.Расширение;
                ПараметрыФайла.Автор = Пользователи.ТекущийПользователь();
                
                // Метод БСП самостоятельно создаст элемент справочника "ЗапросПрисоединенныеФайлы",
                // перенесет двоичные данные в постоянное хранилище (в базу данных или в тома на диске),
                // зарегистрирует запись в регистрах сведений БСП и обновит признак наличия файлов у документа.
                РаботаСФайлами.ДобавитьФайл(ПараметрыФайла, СтрокаФайла.Адрес);
                
            КонецЕсли;
            
        КонецЦикла;
        
        // Если все прошло успешно — фиксируем транзакцию
        ЗафиксироватьТранзакцию();
        Возврат СсылкаНаДокумент;
        
    Исключение
        
        // В случае любой системной ошибки откатываем изменения, чтобы не плодить "битые" ссылки
        ОтменитьТранзакцию();
        
        ЗаписьЖурналаРегистрации("СозданиеЗапросаСФайлами", 
            УровеньЖурналаРегистрации.Ошибка, , , 
            "Произошла ошибка при программном создании запроса: " + ОписаниеОшибки());
            
        ВызватьИсключение "Не удалось завершить операцию: " + КраткоеПредставлениеОшибки(ИнформацияОбОшибке());
        
    КонецПопытки;
    
КонецФункции

Тонкости, о которых важно помнить разработчику

Рассмотрим несколько нюансов, которые помогут вам избежать типичных ошибок при отладке данного механизма:

  1. Объем передаваемых файлов. Помещение файлов во временное хранилище расходует оперативную память сервера. Если пользователи вашей конфигурации 1С:ITIL загружают "тяжелые" вложения (архивы, дампы баз, видеозаписи), обязательно настройте ограничение максимального размера загружаемого файла в настройках работы с файлами БСП.
  2. Управление транзакцией. Мы обернули весь процесс создания документа и добавления файлов в единую транзакцию. Это защищает систему от появления "сиротских" документов, у которых не прикрепились обязательные файлы (например, если сетевой диск с томами хранения файлов оказался временно недоступен в момент вызова метода РаботаСФайлами.ДобавитьФайл). Тем не менее, если бизнес-логика допускает создание документа без файлов в случае технических неполадок, вы можете вынести блок добавления файлов за пределы транзакции записи документа.
  3. Очистка кэша формы. После того как документ успешно создан, а файлы привязаны, не забудьте очистить таблицу СписокВыбранныхФайлов на форме обработки, чтобы при повторном запуске сценария старые вложения не добавились к новому документу повторно.

Используя данный подход, вы сможете спроектировать максимально удобный, эргономичный и быстрый интерфейс для пользователей вашей Service Desk системы в 1С:ITIL, не нарушая при этом строгих стандартов разработки БСП.

← На главную