Перенос графических данных и файлов между базами 1С — типовая задача при интеграциях, миграциях данных или синхронизации распределенных информационных систем. Чаще всего изображения хранятся в реквизитах типа ХранилищеЗначения (например, в справочнике ХранилищеДополнительнойИнформации или в присоединенных файлах).
Разберем основные способы выгрузки таких объектов в файл формата XML и их последующей корректной загрузки в базу-приемник, а также проанализируем важные нюансы оптимизации памяти и сохранения ссылочной целостности.
Посмотрим на классический и наиболее наглядный вариант: получение двоичных данных из хранилища, перевод их в текстовое представление с помощью встроенных функций платформы Base64Строка() и последующее обратное преобразование функцией Base64Значение() при загрузке.
Рассмотрим пример кода для выгрузки изображения в XML-документ:
// Извлекаем двоичные данные из ХранилищаЗначения
ДвоичныеДанныеКартинки = Выборка.Картинка.Получить();
Если ДвоичныеДанныеКартинки <> Неопределено Тогда
КартинкаСтрокой = Base64Строка(ДвоичныеДанныеКартинки);
ЗаписьXML.ЗаписатьНачалоЭлемента("Картинка");
ЗаписьXML.ЗаписатьТекст(КартинкаСтрокой);
ЗаписьXML.ЗаписатьКонецЭлемента();
КонецЕсли;
Разберем, как прочитать эти данные на стороне базы-приемника и записать обратно в реквизит объекта:
// Читаем текстовое значение из XML и создаем новое хранилище
КартинкаСтрокой = ЧтениеXML.Значение;
ДвоичныеДанныеКартинки = Base64Значение(КартинкаСтрокой);
НовыйЭлемент = Справочники.ХранилищеДополнительнойИнформации.СоздатьЭлемент();
НовыйЭлемент.Наименование = ИмяФайла;
НовыйЭлемент.Хранилище = Новый ХранилищеЗначения(ДвоичныеДанныеКартинки, СтепеньСжатия.Максимальное);
НовыйЭлемент.Записать();
Платформа 1С:Предприятие умеет автоматически сериализовать объекты типа ХранилищеЗначения непосредственно через низкоуровневые объекты ЗаписьXML и ЧтениеXML. В этом случае кодирование в Base64 происходит под капотом платформы без необходимости ручного вызова функций конвертации.
Посмотрим на пример выгрузки реквизита:
Если ТипЗнч(ВыгружаемыйРеквизит) = Тип("ХранилищеЗначения") Тогда
ЗаписьXML.ЗаписатьНачалоЭлемента("РеквизитХранилище");
ЗаписьXML.ЗаписатьАтрибут("Тип", "ХранилищеЗначения");
ЗаписатьXML(ЗаписьXML, ВыгружаемыйРеквизит);
ЗаписьXML.ЗаписатьКонецЭлемента();
КонецЕсли;
Проанализируем чтение такого узла в базе-приемнике:
Если ЧтениеXML.Имя = "РеквизитХранилище" И ЧтениеXML.ТипУзла = ТипУзлаXML.НачалоЭлемента Тогда
ТипРеквизита = ЧтениеXML.ПолучитьАтрибут("Тип");
Если ТипРеквизита = "ХранилищеЗначения" Тогда
ЧтениеXML.Прочитать(); // Переходим к содержимому элемента
ДанныеХранилища = ПрочитатьXML(ЧтениеXML);
ОбъектПриемник.Хранилище = ДанныеХранилища;
КонецЕсли;
КонецЕсли;
Для автоматической сериализации прикладных объектов и сложных структур данных можно применить встроенный объект СериализаторXML. Он позволяет трансформировать реквизиты или значения типа ДвоичныеДанные напрямую в формат XML.
// Выгрузка двоичных данных через СериализаторXML
ДвоичныеДанныеФайла = Выборка.Хранилище.Получить();
Если ДвоичныеДанныеФайла <> Неопределено Тогда
СериализаторXML.ЗаписатьXML(ЗаписьXML, ДвоичныеДанныеФайла);
КонецЕсли;
Чтение выполняется парным методом СериализаторXML.ПрочитатьXML(ЧтениеXML), возвращающим исходный объект ДвоичныеДанные.
Если обе информационные базы имеют полностью идентичную конфигурацию, писать собственный программный код не обязательно. Достаточно использовать типовую универсальную обработку «Выгрузка и загрузка данных XML» (доступную на ИТС):
ХранилищеДополнительнойИнформации или справочники присоединенных файлов), а также связанные с ним объекты-владельцы (номенклатуру, контрагентов и т.д.).При реализации выгрузки и загрузки больших объемов графических данных необходимо учитывать несколько критических факторов:
ДокументDOM для файлов большого объема, так как она загружает весь XML-документ целиком в оперативную память. Используйте исключительно потоковое чтение и запись через ЗаписьXML и ЧтениеXML.НачатьТранзакцию() и ЗафиксироватьТранзакцию(), чтобы не перегружать журнал транзакций СУБД.УстановитьСсылкуНового() с исходным уникальным идентификатором (UUID) объекта из базы-источника. Это гарантирует сохранение всех ссылок на владельцев.Новый ХранилищеЗначения(...) передавайте параметр СтепеньСжатия.Максимальное или СтепеньСжатия.Быстрое для оптимизации размера базы данных.Если файлы слишком велики для передачи через текстовый XML, рассмотрим альтернативные механизмы:
V83.COMConnector и прямая запись в приемник без создания промежуточных файлов на диске.