При интеграции нескольких информационных баз 1С часто возникает задача переноса файлов и бинарных данных (картинок, документов PDF, архивов), которые хранятся в реквизитах с типом ХранилищеЗначения. При попытке сделать это "в лоб" через COM-соединение (V83COMConnector) разработчики сталкиваются с проблемой: прямое присвоение вида БазаПриемник.Хранилище = БазаИсточник.Хранилище не работает.
Разберем, почему возникает эта сложность, и рассмотрим проверенные способы переноса данных из хранилища одной базы в другую.
При обращении к внешней базе данных через COM-соединение все возвращаемые объекты непримитивных типов передаются на вызывающую сторону не в виде готовых объектов 1С, а в виде прокси-объектов с типом COMОбъект.
Когда мы вызываем метод Получить() у COM-объекта ХранилищеЗначения, вызывающая программа получает не нативный объект ДвоичныеДанные, а его COM-обертку. Локальный конструктор Новый ХранилищеЗначения() на стороне приемника ожидает на входе только стандартные типы данных 1С, поддерживающие сериализацию. Переданный в него COMОбъект не распознается системой, из-за чего в базу записывается пустое значение или возникает ошибка выполнения.
Для решения этой проблемы необходимо передать данные в таком формате, который COM-соединение сможет корректно маршаллизовать (передать между процессами без потери структуры). Ниже приведены три надежных способа реализации этой задачи.
Строковый тип данных является примитивным и без проблем передается через COM-соединение. Мы можем преобразовать двоичные данные в строку формата Base64 на стороне одной базы, передать эту строку по COM и восстановить двоичные данные на стороне другой базы.
Рассмотрим по шагам, как это реализовать, если перенос инициирован со стороны базы-источника (База 2) в базу-приемник (База 1):
Base64Строка().Base64Значение().NewObject().Посмотрим на практический пример кода:
// 1. Получаем двоичные данные из хранилища в базе-источнике
ДвоичныеДанныеИсточника = ВыборкаДетальныеЗаписи.Хранилище.Получить();
// 2. Кодируем двоичные данные в Base64-строку
ДвоичныеСтрокой = Base64Строка(ДвоичныеДанныеИсточника);
// Предположим, что База1 — это наше активное COM-соединение с базой-приемником
// 3. Преобразуем Base64-строку в объект ДвоичныеДанные на стороне приемника
ОлеФайл = База1.Base64Значение(ДвоичныеСтрокой);
// 4. Помещаем полученный объект в новое ХранилищеЗначения базы-приемника
// Используем метод NewObject для создания объекта ХранилищеЗначения в контексте Базы 1
СпрОбъектПриемник = База1.Справочники.Номенклатура.НайтиПоКоду("00001").ПолучитьОбъект();
СпрОбъектПриемник.Хранилище = База1.NewObject("ХранилищеЗначения", ОлеФайл, База1.NewObject("СжатиеДанных"));
СпрОбъектПриемник.Записать();
Объект типа ХранилищеЗначения по умолчанию поддерживает XML-сериализацию. Платформа 1С при сериализации автоматически кодирует бинарное содержимое хранилища в Base64. Это позволяет передать объект целиком в виде XML-текста, минуя ручное извлечение двоичных данных.
Проанализируем этот элегантный способ:
// На стороне источника (База 2) сериализуем ХранилищеЗначения в строку XML
СтрокаXML = COMСоединение.XMLСтрока(РезЗапросаБаза2.Хранилище);
// На стороне приемника (База 1) десериализуем XML-строку обратно в объект ХранилищеЗначения
База1.Хранилище = XMLЗначение(Тип("ХранилищеЗначения"), СтрокаXML);
Этот метод значительно сокращает количество строк кода и исключает ошибки ручного преобразования типов.
Если объем передаваемых файлов очень велик (сотни мегабайт или гигабайты), передача файлов "в памяти" через Base64 может привести к перерасходу оперативной памяти на сервере и аварийному завершению рабочих процессов 1С. В таких случаях надежнее использовать промежуточную выгрузку на диск.
Разберем алгоритм этого метода:
ДвоичныеДанные.Записать(ПутьКФайлу).ДвоичныеДанные, считывая файл с диска: Новый ДвоичныеДанные(ПутьКФайлу).Важно помнить, что технология COM-соединения (V83COMConnector) считается устаревшей и имеет ряд серьезных ограничений: она работает только под управлением ОС Windows, требует обязательной регистрации Windows-библиотеки comcntr.dll и крайне чувствительна к несовпадению версий платформы клиента и сервера.
Для надежного обмена бинарными данными в современных конфигурациях рекомендуется использовать HTTP-сервисы. Передача файлов напрямую в теле POST-запроса (например, с использованием заголовка Content-Type: application/octet-stream) работает быстрее, стабильнее, не нагружает оперативную память процесса COM и полностью независима от операционной системы и версий платформы 1С.