Передача присоединённых файлов в Конвертации данных 2 решается так: перед выгрузкой документа запросом собираются его файлы, складываются в таблицу значений с двоичными данными, таблица сериализуется в строку через СериализаторXDTO и передаётся в параметре конвертации. В приёмнике в обработчике «После загрузки» правила конвертации объекта строка превращается обратно в таблицу, а файлы записываются туда, где их хранит конфигурация-приёмник, — например, в табличную часть документа.

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

Когда нужен такой обходной путь

В обменах между старыми и новыми конфигурациями (например, УПП 1.3 и УП 2.x) или между доработанными базами часто встречается:

  • в источнике файлы — элементы справочника с владельцем-документом и хранилищем значения;
  • в приёмнике — табличная часть документа, собственный справочник или подсистема файлов БСП с версиями файлов;
  • правила конвертации документа уже есть, и добавлять сложную цепочку правил для справочника файлов не хочется.

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

Общая схема

  1. В источнике, перед выгрузкой документа, запросом получаем его файлы.
  2. Каждый файл — строка таблицы значений: имя, расширение, двоичные данные.
  3. Таблицу сериализуем в строку XML.
  4. Строку передаём в параметре конвертации вместе с документом.
  5. В приёмнике после загрузки документа разбираем строку и записываем файлы.
Передача присоединённых файлов в КД2: файлы упаковываются вместе с документом и распаковываются в приёмнике
Передача присоединённых файлов в КД2: файлы упаковываются вместе с документом и распаковываются в приёмнике

Настройка выполняется в конфигурации «Конвертация данных» редакции, поддерживающей формат КД 2 (например, 3.1 в режиме КД 2). Правила конвертации объекта и свойств для самого документа считаем уже созданными.

Шаг 1. Параметр конвертации

На закладке параметров правил создайте параметр, например ФайлыДокумента. Ему нужен признак передачи в приёмник при выгрузке, чтобы значение попало в файл обмена.

Важно, в какой момент параметр попадёт в файл. Параметры, заполненные до начала выгрузки, записываются в начало файла. Нам же нужно передавать значение для каждого документа отдельно, прямо перед ним. Для этого в обработке универсального обмена есть служебная процедура передачи одного параметра в приёмник в момент выгрузки (ПередатьОдинПараметрВПриемник). Проверьте её наличие и сигнатуру в той версии обработки, с которой работают ваши правила.

Шаг 2. Сбор файлов и сериализация в источнике

Вспомогательные функции удобно разместить в алгоритмах правил:

1С
// Собирает присоединённые файлы документа в таблицу значений.
Функция ТаблицаФайловДокумента(СсылкаНаДокумент)

	Файлы = Новый ТаблицаЗначений;
	Файлы.Колонки.Добавить("ИмяФайла", Новый ОписаниеТипов("Строка"));
	Файлы.Колонки.Добавить("Расширение", Новый ОписаниеТипов("Строка"));
	Файлы.Колонки.Добавить("Данные", Новый ОписаниеТипов("ДвоичныеДанные"));

	Запрос = Новый Запрос;
	Запрос.Текст =
	"ВЫБРАТЬ
	|	Хранилище.Наименование КАК ИмяФайла,
	|	Хранилище.ИмяФайла КАК ПолноеИмя,
	|	Хранилище.Хранилище КАК Хранилище
	|ИЗ
	|	Справочник.ХранилищеДополнительнойИнформации КАК Хранилище
	|ГДЕ
	|	Хранилище.Объект = &Документ
	|	И НЕ Хранилище.ПометкаУдаления";
	Запрос.УстановитьПараметр("Документ", СсылкаНаДокумент);

	Выборка = Запрос.Выполнить().Выбрать();
	Пока Выборка.Следующий() Цикл
		Данные = Выборка.Хранилище.Получить();
		Если ТипЗнч(Данные) <> Тип("ДвоичныеДанные") Тогда
			Продолжить; // Пустое или нестандартное содержимое не передаём.
		КонецЕсли;
		Строка = Файлы.Добавить();
		Строка.ИмяФайла = Выборка.ИмяФайла;
		Строка.Расширение = РасширениеФайла(Выборка.ПолноеИмя);
		Строка.Данные = Данные;
	КонецЦикла;

	Возврат Файлы;

КонецФункции

// Возвращает расширение файла без точки.
Функция РасширениеФайла(ПолноеИмя)

	Части = СтрРазделить(ПолноеИмя, ".");
	Возврат ?(Части.Количество() > 1, НРег(Части[Части.ВГраница()]), "");

КонецФункции

// Сериализует значение в строку XML.
Функция ЗначениеВСтрокуXML(Значение)

	ЗаписьXML = Новый ЗаписьXML;
	ЗаписьXML.УстановитьСтроку();
	СериализаторXDTO.ЗаписатьXML(ЗаписьXML, Значение, НазначениеТипаXML.Явное);
	Возврат ЗаписьXML.Закрыть();

КонецФункции

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

Колонку Данные объявляйте с типом ДвоичныеДанные: таблица значений с примитивными типами и двоичными данными сериализуется XDTO без проблем, а произвольные типы (ссылки на объекты базы-источника) в приёмнике не прочитаются. Передавайте только строки, числа, даты и двоичные данные.

Обработчик «Перед выгрузкой» правила документа

1С
// ПКО документа, обработчик «Перед выгрузкой».
ФайлыДокумента = ТаблицаФайловДокумента(Источник.Ссылка);
Если ФайлыДокумента.Количество() > 0 Тогда
	ПередатьОдинПараметрВПриемник("ФайлыДокумента", ЗначениеВСтрокуXML(ФайлыДокумента));
КонецЕсли;

Если файлов нет, параметр не передаём — так приёмник не перезапишет файлы документа пустым списком. Но учтите обратное: удаление файла в источнике при таком подходе в приёмник не попадёт.

Шаг 3. Разбор и запись в приёмнике

В приёмнике значение параметра доступно в структуре Параметры. Обработчик «После загрузки» правила документа:

1С
// ПКО документа, обработчик «После загрузки».
СтрокаФайлов = Неопределено;
Если Параметры.Свойство("ФайлыДокумента", СтрокаФайлов) И ЗначениеЗаполнено(СтрокаФайлов) Тогда

	ЧтениеXML = Новый ЧтениеXML;
	ЧтениеXML.УстановитьСтроку(СтрокаФайлов);
	ФайлыДокумента = СериализаторXDTO.ПрочитатьXML(ЧтениеXML);
	ЧтениеXML.Закрыть();

	Объект.ПриложенныеФайлы.Очистить();
	Для Каждого ОписаниеФайла Из ФайлыДокумента Цикл
		СтрокаТЧ = Объект.ПриложенныеФайлы.Добавить();
		СтрокаТЧ.ИмяФайла = ОписаниеФайла.ИмяФайла;
		СтрокаТЧ.Расширение = ОписаниеФайла.Расширение;
		СтрокаТЧ.Файл = Новый ХранилищеЗначения(ОписаниеФайла.Данные, Новый СжатиеДанных(9));
	КонецЦикла;

	// Значение относится только к этому документу.
	Параметры.ФайлыДокумента = Неопределено;

КонецЕсли;

Табличная часть ПриложенныеФайлы — пример доработки приёмника. Обнуление параметра в конце обязательно: иначе следующий документ без файлов получит вложения предыдущего.

Если в приёмнике подсистема файлов БСП

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

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

Объём и производительность

  • Base64. Двоичные данные в XML кодируются в Base64 — это примерно плюс треть к размеру. Сотня сканов по 5 МБ превращается в файл обмена почти на 700 МБ.
  • Ограничения. Передавайте только нужные типы (PDF, сканы), отсекайте файлы больше заданного размера и пишите в журнал регистрации, что было пропущено.
  • Повторная выгрузка. Документ попадает в обмен при любом изменении. Если файлы не менялись, передавать их снова незачем — храните признак или хеш переданных файлов.
  • Память. Сериализация большой таблицы в строку целиком держит её в памяти сервера. Для тяжёлых вложений лучше отдельный канал передачи файлов (например, через HTTP-сервис), а обменом передавать только ссылки.

Типичные ошибки

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

Обмены на правилах КД 2 и КД 3, в том числе с файлами и доработанными конфигурациями, я настраиваю в рамках услуги обмен между базами 1С; если файлы большие и их много, обсуждаем отдельный канал через интеграцию по API.

Коротко

  • Файлы документа собираются в таблицу значений с примитивными типами и двоичными данными.
  • Таблица сериализуется в строку через СериализаторXDTO и передаётся параметром конвертации в момент выгрузки документа.
  • В приёмнике строка читается обратно и файлы записываются в нужное хранилище; параметр после этого обнуляется.
  • Для подсистемы файлов БСП добавляйте файлы после записи владельца — в обработчике после загрузки данных.
  • Ограничивайте объём: Base64 увеличивает размер, а повторная передача неизменных файлов бессмысленна.