Как исправить ошибку отображения типа base64Binary в ДвоичныеДанные при передаче данных между клиентом и сервером?

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

При разработке отчетов и обработок на управляемых формах 1С разработчики нередко сталкиваются с ошибкой сериализации XDTO при попытке вернуть управление с сервера на клиент. Чаще всего текст ошибки выглядит следующим образом: «Ошибка передачи данных между клиентом и сервером. Значение недопустимого типа... Ошибка преобразования данных XDTO: НачалоСвойства: picture... Ошибка отображения типов: Отображение типа base64Binary в тип ДвоичныеДанные».

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

Почему возникает ошибка преобразования XDTO

Выясним причину такого поведения платформы. В управляемом приложении при выполнении контекстного серверного вызова с директивой &НаСервере платформа полностью сериализует контекст управляемой формы и все ее реквизиты в формат XML/XDTO для передачи на сервер, а затем выполняет обратную десериализацию при возврате на клиент. Сбой происходит в следующих случаях:

  1. Передача ТабличногоДокумента в контексте формы. Если реквизит формы типа ТабличныйДокумент содержит внедренные графические объекты, при автоматической сериализации встроенный механизм XDTO не всегда может корректно сопоставить внутреннюю структуру данных типа base64Binary с типом ДвоичныеДанные.
  2. Использование отложенной загрузки в конструкторе. Вызов конструктора вида Новый Картинка(Источник, Ложь) задает платформе режим хранения ссылки на внешний файл/поток без прямого внедрения данных. При передаче между контекстами связь с источником теряется, и десериализация завершается аварийно.
  3. Нестандартные или поврежденные метаданные файлов. Если исходные файлы содержат специфические цветовые профили или блоки EXIF с недопустимыми для стандарта XML управляющими символами, механизм XDTO не может корректно упаковать свойство picture.

Способ 1. Использование функций без контекста и локального табличного документа

Разберем наиболее архитектурно правильный подход в управляемом приложении. Чтобы исключить автоматическую сериализацию «тяжелого» контекста формы, переведем формирование отчета в процедуру или функцию с директивой &НаСервереБезКонтекста. Табличный документ формируется в локальной переменной на сервере и возвращается на клиент как результат функции.

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


&НаСервереБезКонтекста
Функция СформироватьОтчетНаСервере(ПараметрыОтчета)
    ТабДок = Новый ТабличныйДокумент;
    Макет = Отчеты.ПрайсЛист.ПолучитьМакет("ОсновнойМакет");
    ОбластьСтрока = Макет.ПолучитьОбласть("СтрокаНоменклатуры");
    
    // Заполнение макета и вывод областей
    // ...
    
    Возврат ТабДок;
КонецФункции

&НаКлиенте
Процедура Сформировать(Команда)
    ПараметрыОтчета = Новый Структура;
    // Заполняем структуру параметров
    
    РеквизитТабДокФормы = СформироватьОтчетНаСервере(ПараметрыОтчета);
КонецПроцедуры

Такой подход полностью разгружает трафик между клиентом и сервером и предотвращает возникновение ошибок сериализации XDTO реквизитов формы.

Способ 2. Передача табличного документа через Временное хранилище

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

Разберем по шагам данный алгоритм:

  1. На стороне сервера формируем локальный ТабличныйДокумент.
  2. Помещаем готовый табличный документ во временное хранилище по уникальному идентификатору формы.
  3. На клиенте считываем результат из хранилища и помещаем в отображаемый реквизит формы.

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


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

&НаКлиенте
Процедура ВыполнитьФормирование(Команда)
    АдресВХ = ПоместитьТабДокВХранилище();
    Элементы.ТабличныйДокументПоле.Очистить();
    РеквизитФормыТабДок = ПолучитьИзВременногоХранилища(АдресВХ);
КонецПроцедуры

Способ 3. Преобразование двоичных данных через Base64Строка

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

Рассмотрим, как выполнить эту операцию:


&НаСервере
Функция ПолучитьСтрокуКартинкиНаСервере(СсылкаНаНоменклатуру)
    // Получаем ДвоичныеДанные из хранилища объекта
    ДвоичныеДанные = СсылкаНаНоменклатуру.ФайлКартинки.Хранилище.Получить();
    
    Если ДвоичныеДанные = Неопределено Тогда
        Возврат "";
    КонецЕсли;
    
    // Преобразуем ДвоичныеДанные в строку Base64
    Возврат Base64Строка(ДвоичныеДанные);
КонецФункции

&НаКлиенте
Процедура ОтобразитьКартинкуНаКлиенте(СтрокаBase64)
    Если ПустаяСтрока(СтрокаBase64) Тогда
        Возврат;
    КонецЕсли;
    
    // Восстанавливаем ДвоичныеДанные на клиенте
    ДвоичныеДанные = Base64Значение(СтрокаBase64);
    ОбъектКартинка = Новый Картинка(ДвоичныеДанные);
    
    // Использование полученного объекта Картинка
КонецПроцедуры

Способ 4. Корректная инициализация объекта Картинка

Проанализируем параметры конструктора Новый Картинка. Если в коде использовалась конструкция с отложенной инициализацией:

КартинкаОбъект = Новый Картинка(АдресФайла, Ложь);

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


// Создание объекта с полным внедрением двоичных данных
КартинкаОбъект = Новый Картинка(ДвоичныеДанные);
РисунокТабДока.Картинка = КартинкаОбъект;

Также рекомендуется передавать в служебные серверные процедуры ссылку на объект номенклатуры (СсылкаНаНоменклатуру), а не реквизиты составного типа или ссылки на вложенные файлы напрямую через параметры серверного вызова.

← На главную