Как выгрузить изображение из справочника 1С Номенклатура в Delphi через COM-соединение

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

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

Анализ проблемы получения двоичных данных

Типичная ошибка при работе с изображениями через COM заключается в попытке обработать полученную переменную как стандартный массив байтов или поток Delphi. Проанализируем ситуацию: когда мы выполняем запрос к базе 1С и обращаемся к полю ОсновноеИзображение, мы получаем ссылку на элемент справочника. Чтобы добраться до самой картинки, нам нужно обратиться к реквизиту (обычно это Хранилище), извлечь из него значение и преобразовать его в ДвоичныеДанные.

В Delphi результат такого обращения помещается в переменную типа OleVariant. Попытка записать эту переменную напрямую в TMemoryStream через метод ms.Write не приведет к успеху, так как OleVariant в данном случае содержит не массив байтов, а указатель на интерфейс IDispatch объекта 1С ДвоичныеДанные.

Решение через встроенные методы объекта 1С

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


while querySelection.Следующий() do
begin
  // Получаем объект ДвоичныеДанные из хранилища 1С
  vvar := querySelection.ОсновноеИзображение.Хранилище.Получить().ПолучитьДвоичныеДанные();
  
  // Вместо ручного копирования в Stream, вызываем метод объекта 1С
  // Это сохранит файл напрямую средствами платформы 1С
  vvar.Записать('d:\картинка.jpg');
end;

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

Работа с изображениями без сохранения на диск

Иногда требуется загрузить изображение напрямую в компонент TImage, не создавая временных файлов. В этом случае нам придется работать с потоками. Разберем, как передать данные через IStream или Base64. Одним из современных и надежных способов является передача изображения в виде строки Base64.

На стороне 1С мы можем преобразовать двоичные данные в строку:


// В коде 1С или через COM-вызов
СтрокаBase64 = Base64Строка(ДвоичныеДанные);

В Delphi мы получаем эту строку и декодируем её. Рассмотрим пример с использованием стандартных библиотек:


var
  Base64Str: string;
  InStream: TStringStream;
  OutStream: TMemoryStream;
begin
  Base64Str := vvarBase64; // Полученная из 1С строка
  InStream := TStringStream.Create(Base64Str);
  OutStream := TMemoryStream.Create;
  try
    TNetEncoding.Base64.Decode(InStream, OutStream);
    OutStream.Position := 0;
    Image1.Picture.LoadFromStream(OutStream);
  finally
    InStream.Free;
    OutStream.Free;
  end;
end;

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

Важные нюансы архитектуры (x86 и x64)

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

  1. Разрядность процессов: Если ваша программа на Delphi скомпилирована под 32 бита (Win32), а серверная часть 1С работает исключительно в 64-битном режиме, прямое создание объекта V83.COMConnector может завершиться ошибкой "Класс не зарегистрирован".
  2. Решение через COM+: В таких случаях мы рекомендуем настроить приложение в Component Services (dcomcnfg). Нужно создать пустую COM+ библиотеку и добавить в неё компонент 1С. Это позволит Windows пробросить вызовы между процессами разной разрядности.
  3. Утечки памяти: При циклическом обращении к объектам 1С через COM в Delphi, объекты могут не сразу удаляться из памяти. Рекомендуется явно присваивать Unassigned переменным типа OleVariant после завершения работы с ними.

Альтернативный подход через HTTP-сервисы

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

Разберем преимущества HTTP-запросов для получения картинок:

Для реализации в Delphi мы можем использовать компоненты TNetHTTPClient. Посмотрим на логику:


var
  Response: IHTTPResponse;
begin
  // Отправляем запрос к заранее созданному HTTP-сервису в 1С
  Response := NetHTTPClient1.Get('http://server/base/hs/get_photo/00000327188');
  if Response.StatusCode = 200 then
  begin
    Image1.Picture.LoadFromStream(Response.ContentStream);
  end;
end;

Заключение

Подводя итог, можно сказать, что для быстрого исправления текущего кода достаточно использовать метод vvar.Записать(ПутьКФайлу). Однако, если вы планируете развивать систему и делать её более устойчивой, проанализируйте возможность перехода на передачу данных в формате Base64 или использование HTTP-сервисов. Это позволит избежать проблем с разрядностью систем и обеспечит более высокую производительность при работе с изображениями в связке Delphi и 1С.

← На главную