Как перенести фото из одной базы 1С в другую через COM-соединение?

Программист 1С v8.3 (Обычные формы) 1С:Управление торговлей Торговля и дистрибуция
← На главную

При работе с COM-соединениями в 1С часто возникает задача переноса данных, включая изображения, из одной информационной базы в другую. Прямая передача сложных объектов, таких как Картинка или ХранилищеЗначения, через COM невозможна или работает нестабильно. Вместо объекта мы получаем в принимающей базе лишь ссылку на COMОбъект, с которым нельзя напрямую работать как с исходным типом данных. Для ознакомления с основами подключения подойдёт руководство по работе с COM-объектом в 1С.

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

Решение 1: Перенос через временный файл

Этот метод основан на простом принципе: мы не можем передать саму картинку, но можем передать путь к файлу, в который она сохранена. Диск в данном случае выступает в роли "посредника" между двумя базами.

Рассмотрим алгоритм по шагам:

  1. Устанавливаем COM-соединение с базой-источником.
  2. В базе-источнике получаем нужный объект (например, элемент справочника "Номенклатура") и из его реквизита типа ХранилищеЗначения извлекаем саму картинку.
  3. Сохраняем полученный объект Картинка во временный файл на диске с помощью метода Записать(). Очень важно указать расширение файла, например, ".jpg" или ".png".
  4. В базе-приемнике, используя COM-объект, создаем новый объект Picture (английское название для "Картинка"), передавая в качестве параметра путь к временному файлу.
  5. Создаем в базе-приемнике новое ХранилищеЗначения из этого объекта Picture.
  6. Записываем полученное хранилище в соответствующий реквизит нового или обновляемого объекта в базе-приемнике.

Посмотрим на практический пример кода, основанный на обсуждении. Представим, что у нас уже есть COM-соединение с базой-источником (переменная V8) и мы хотим перенести основное изображение для номенклатуры с определенным кодом.


// V8 - это уже установленное COM-соединение с базой-источником.
// Например, V8 = Новый ComОбъект("V82.ComConnector").Connect(...);

// 1. Определяем путь к временному файлу
// ОБЯЗАТЕЛЬНО указываем расширение!
ПутьКВременномуФайлу = КаталогВременныхФайлов() + "temp_image.jpg";

// 2. В базе-источнике находим объект и получаем его картинку
// Этот код выполняется в текущей (принимающей) базе.
// Мы обращаемся к данным удаленной базы через COM-объект.
СсылкаНаНоменклатуруИсточник = Справочники.Номенклатура.НайтиПоКоду("ТОВ-00123");
Если ЗначениеЗаполнено(СсылкаНаНоменклатуруИсточник.ОсновноеИзображение) Тогда
    
    // Получаем объект Картинка из хранилища в базе-источнике
    КартинкаИзИсточника = СсылкаНаНоменклатуруИсточник.ОсновноеИзображение.Хранилище.Получить();
    
    Если КартинкаИзИсточника <> Неопределено Тогда
        // 3. Сохраняем картинку во временный файл
        Попытка
            КартинкаИзИсточника.Записать(ПутьКВременномуФайлу);
        Исключение
            Сообщить("Не удалось сохранить изображение во временный файл: " + ОписаниеОшибки());
            Возврат;
        КонецПопытки;
        
        // 4. В базе-приемнике находим соответствующий элемент
        НайденнаяСсылкаПриемник = V8.Справочники.Номенклатура.НайтиПоКоду("ТОВ-00123");
        
        Если ЗначениеЗаполнено(НайденнаяСсылкаПриемник.Ссылка) Тогда
            // Создаем COM-объект Картинки из файла
            // ВАЖНО: используем английское имя "Picture"
            V8Картинка = V8.NewObject("Picture", ПутьКВременномуФайлу);
            
            // Создаем COM-объект ХранилищаЗначения
            V8Хранилище = V8.NewObject("ХранилищеЗначения", V8Картинка);
            
            // Получаем объект для записи в базе-приемнике
            ХДИ_Объект = НайденнаяСсылкаПриемник.ОсновноеИзображение.ПолучитьОбъект();
            
            // 5. Заполняем и записываем
            ХДИ_Объект.ВидДанных = V8.Перечисления.ВидыДополнительнойИнформацииОбъектов.Изображение;
            ХДИ_Объект.Хранилище = V8Хранилище;
            ХДИ_Объект.Записать();
            
            Сообщить("Изображение для номенклатуры успешно перенесено!");
        КонецЕсли;
        
        // Не забываем удалить временный файл
        УдалитьФайлы(ПутьКВременномуФайлу);
    КонецЕсли;
КонецЕсли;

Ключевые моменты, на которые стоит обратить внимание:

Решение 2: Перенос с помощью Base64 (рекомендуемый способ)

Этот метод является более современным, надежным и универсальным. Он полностью исключает операции с файловой системой, что делает его более стабильным, особенно при работе на сервере, где права доступа к файлам могут быть ограничены. Суть метода в преобразовании двоичных данных изображения в обычную текстовую строку.

Проанализируем алгоритм:

  1. Устанавливаем COM-соединение с базой-источником.
  2. В базе-источнике получаем двоичные данные изображения (объект ДвоичныеДанные).
  3. На стороне базы-источника преобразуем эти двоичные данные в текстовую строку с помощью функции Base64Строка(). Это критически важный шаг, так как вызов должен произойти в контексте удаленной базы.
  4. Полученная текстовая строка без проблем передается через COM-соединение в базу-приемник.
  5. В базе-приемнике мы преобразуем строку обратно в двоичные данные с помощью функции Base64Значение().
  6. Из полученных двоичных данных создаем новый объект Картинка.
  7. Сохраняем картинку в ХранилищеЗначения в базе-приемнике.

Посмотрим, как это выглядит в коде. Этот подход элегантнее и не требует работы с файлами.


// V8Connect - это установленное COM-соединение с базой-источником.

// В базе-приемнике (где выполняется этот код)

// Получаем ссылку на объект в удаленной базе
СсылкаНаОбъектCOM = V8Connect.Справочники.Номенклатура.НайтиПоКоду("ТОВ-00123");

Если СсылкаНаОбъектCOM.Пустая() Тогда
    Сообщить("Объект в базе-источнике не найден!");
    Возврат;
КонецЕсли;

ХранилищеCOM = СсылкаНаОбъектCOM.ОсновноеИзображение.Хранилище;

// КЛЮЧЕВОЙ МОМЕНТ:
// Мы не можем просто сделать ХранилищеCOM.Получить(), так как это вернет COMОбъект.
// Поэтому все операции по извлечению данных и кодированию нужно выполнять
// в контексте удаленной базы, вызывая методы через COM-соединение.
СтрокаBase64 = V8Connect.Base64Строка(ХранилищеCOM.Получить().ПолучитьДвоичныеДанные());

// Проверяем, что получили строку
Если ТипЗнч(СтрокаBase64) = Тип("Строка") И Не ПустаяСтрока(СтрокаBase64) Тогда

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

Выводы и рекомендации

Мы рассмотрели два рабочих способа переноса изображений между базами 1С через COM-соединение.

При организации массового обмена данными также стоит помнить об оптимизации. Для максимальной производительности используйте V8.COMConnector вместо V8.Application, так как он не запускает полный графический интерфейс приложения. Если нужно перенести тысячи изображений, организуйте пакетную обработку и рассмотрите возможность выполнения операции в фоновом или регламентном задании, чтобы не мешать работе пользователей. При необходимости комплексной передачи объектов можно воспользоваться готовым решением для универсального переноса данных между конфигурациями 1С по COM.

← На главную