Как передать данные типа ХранилищеЗначения через COM-соединение в 1С

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

При организации обмена между базами данных 1С с использованием технологии V83.COMConnector разработчики часто сталкиваются с трудностями при передаче сложных типов данных. Одной из таких задач является перенос содержимого реквизитов с типом ХранилищеЗначения (например, при переносе прикрепленных файлов, изображений или дополнительных сведений из справочника Хранилище дополнительной информации).

Прямое присвоение значения реквизита из COM-объекта в объект базы-приемника невозможно, так как COM-сервер возвращает COM-объект (прокси), который не может быть напрямую записан в базу-приемник. Разберем различные способы решения этой задачи, их преимущества, ограничения и особенности реализации.

Способ 1. Сериализация в XML-строку (стандартный механизм платформы)

Проанализируем самый лаконичный способ, который основан на стандартных функциях платформы XMLСтрока и XMLЗначение. Идея заключается в том, чтобы сериализовать объект ХранилищеЗначения в текстовую XML-строку на стороне базы-источника через вызов ее контекста, а затем восстановить его в базе-приемнике.

Рассмотрим пример кода:


// конн - установленное COM-соединение с базой-источником
// Выгружаем ХранилищеЗначения в строку XML через контекст COM-соединения
СтрокаXML = конн.XMLСтрока(СтрокаТЗ.Хранилище);

// В базе-приемнике преобразуем строку обратно в объект типа ХранилищеЗначения
ПриемникОбъект.Хранилище = XMLЗначение(Тип("ХранилищеЗначения"), СтрокаXML);

Важные нюансы использования данного способа:

  1. Тип хранимого значения: Способ работает корректно только тогда, когда внутри хранилища находятся сериализуемые типы (простые типы, структуры или ДвоичныеДанные). Если внутри хранилища записана ссылка или прикладной объект базы-источника, метод XMLЗначение завершится ошибкой либо создаст некорректную битую ссылку из-за несовпадения внутренних идентификаторов баз.
  2. Расход оперативной памяти: Преобразование двоичных данных в текстовый формат XML увеличивает объем передаваемой строки примерно на треть. При передаче больших файлов через COM-маршалинг это может привести к повышенному расходу памяти процесса.

Способ 2. Извлечение ДвоичныхДанных и кодирование в Base64

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

Посмотрим на пример реализации:


// 1. Извлекаем данные из ХранилищаЗначения в контексте базы-источника
ДвоичныеДанныеИсточника = СтрокаТЗ.Хранилище.Получить();

Если ДвоичныеДанныеИсточника <> Неопределено Тогда
    // 2. Преобразуем ДвоичныеДанные в строку Base64 методами базы-источника
    СтрокаBase64 = конн.Base64Строка(ДвоичныеДанныеИсточника);
    
    // 3. Восстанавливаем ДвоичныеДанные в базе-приемнике
    ДвоичныеДанныеПриемника = Base64Значение(СтрокаBase64);
    
    // 4. Помещаем в ХранилищеЗначения с явным указанием степени сжатия
    ПриемникОбъект.Хранилище = Новый ХранилищеЗначения(
        ДвоичныеДанныеПриемника, 
        СтепеньСжатияХранилищаЗначения.Сжатие9
    );
КонецЕсли;

Этот подход позволяет гибко управлять сжатием данных (СтепеньСжатияХранилищаЗначения) и точно контролировать тип извлекаемых данных.

Способ 3. Передача через временный файл на общем ресурсе

Когда речь идет о переносе файлов большого размера (сканы документов, PDF-файлы, архивы от нескольких десятков мегабайт), передача гигантских строк через COM-интерфейс может приводить к ошибкам «Недостаточно памяти». В таких ситуациях наиболее надежным решением является выгрузка во временный файл на диске.

Рассмотрим алгоритм передачи через файловую систему:

  1. На стороне базы-источника получаем ДвоичныеДанные из хранилища и сохраняем их во временный файл на доступном сетевом ресурсе методом Записать().
  2. В базе-приемнике инициализируем ДвоичныеДанные из этого файла конструктором Новый ДвоичныеДанные(ПутьКФайлу).
  3. Помещаем полученные данные в реквизит объекта-приемника и удаляем временный файл с диска.

// Получаем бинарные данные из хранилища источника
ДвоичныеДанныеИсточника = СтрокаТЗ.Хранилище.Получить();

Если ДвоичныеДанныеИсточника <> Неопределено Тогда
    ИмяВременногоФайла = ПолучитьИмяВременногоФайла();
    
    // Записываем файл на диск через метод объекта источника
    ДвоичныеДанныеИсточника.Записать(ИмяВременногоФайла);
    
    // Считываем файл в базе-приемнике
    ДвоичныеДанныеПриемника = Новый ДвоичныеДанные(ИмяВременногоФайла);
    ПриемникОбъект.Хранилище = Новый ХранилищеЗначения(ДвоичныеДанныеПриемника);
    
    // Очищаем временный файл
    УдалитьФайлы(ИмяВременногоФайла);
КонецЕсли;

Способ 4. Сериализация структур через СериализаторXDTO

Если в ХранилищеЗначения хранится сложная структура, список значений или таблица простых типов, для надежной передачи структуры без потери типизации целесообразно использовать объект СериализаторXDTO.

Посмотрим, как организовать такую передачу:


// В базе-источнике извлекаем структуру и сериализуем в XML через XDTO
ЗначениеХранилища = СтрокаТЗ.Хранилище.Получить();

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

// В базе-приемнике десериализуем XML обратно в структуру
ЧтениеXML = Новый ЧтениеXML;
ЧтениеXML.УстановитьСтроку(СтрокаXML);
ВосстановленноеЗначение = СериализаторXDTO.ПрочитатьXML(ЧтениеXML);
ЧтениеXML.Закрыть();

ПриемникОбъект.Хранилище = Новый ХранилищеЗначения(ВосстановленноеЗначение);

Ограничения COM-соединения и современные альтернативы

При проектировании интеграций через COM важно помнить о системных ограничениях данной технологии:

  1. Платформенная зависимость: COM-соединение поддерживается только в операционной системе Windows. Если сервер 1С работает под управлением Linux, использование COM невозможно.
  2. Разрядность процессов: При несовпадении разрядности клиента и сервера (32-бит и 64-бит) требуется настройка отдельного COM+ приложения в службах компонентов Windows.
  3. Утечки памяти: COM-сессии удерживают оперативную память до полного закрытия соединения. При переносе большого массива данных порциями рекомендуется периодически переподключаться или очищать переменные соединения.

В современной разработке на платформе 1С для передачи двоичных данных и содержимого хранилищ вместо COM рекомендуется использовать платформонезависимые HTTP-сервисы или Web-сервисы, которые позволяют передавать поток байтов без ограничений разрядности и операционной системы.

← На главную