В процессе интеграции 1С с внешними системами через HTTP-сервисы часто возникает задача передачи табличных документов. Наиболее распространенный формат передачи двоичных данных в текстовых протоколах (JSON, XML) — это кодировка Base64. Однако на стороне получателя разработчики нередко сталкиваются с ошибкой «Ошибка формата потока» при попытке преобразовать полученную строку обратно в ТабличныйДокумент. В этой статье мы подробно разберем, как правильно обрабатывать такие данные, проанализируем причины ошибок и рассмотрим рабочие примеры кода.
Когда мы получаем строку Base64, которая должна содержать ТабличныйДокумент, мы выполняем стандартную последовательность действий: преобразуем строку в ДвоичныеДанные, открываем поток и вызываем метод Прочитать(). Если в этот момент возникает ошибка формата, это означает, что содержимое потока не соответствует ожиданиям метода Прочитать(). Рассмотрим основные причины этой ситуации:
ЗначениеВДвоичныеДанные(), а получатель пытается использовать ТабДок.Прочитать(). Это принципиально разные механизмы: первый создает сериализованный объект 1С, второй ожидает файл формата MXL.base64Binary, платформа может автоматически декодировать их в двоичные данные, и повторный вызов Base64Значение() приведет к порче данных.Если HTTP-сервис корректно сохранил табличный документ в поток в формате MXL, то на стороне клиента мы должны использовать метод ОткрытьПотокДляЧтения(). Давайте разберем этот алгоритм по шагам.
Проанализируем пример кода, который должен работать в большинстве стандартных случаев:
// Предположим, что СтрокаBase64 — это данные, полученные из сервиса
ДвоичныеДанные = Base64Значение(СтрокаBase64);
// Открываем поток для чтения из двоичных данных
Поток = ДвоичныеДанные.ОткрытьПотокДляЧтения();
ТабДок = Новый ТабличныйДокумент;
Попытка
// Важно: можно явно указать формат файла, если вы в нем уверены
ТабДок.Прочитать(Поток, ТипФайлаТабличногоДокумента.MXL);
Поток.Закрыть();
// Выводим результат в поле на форме
ЭлементыФормы.ПолеТабличногоДокумента1.Вывести(ТабДок);
Исключение
Поток.Закрыть();
Сообщить("Не удалось прочитать документ: " + ОписаниеОшибки());
КонецПопытки;
Важный нюанс: Метод ОткрытьПотокДляЧтения() доступен в платформе 8.3. Если вы работаете на более старых версиях, вам придется использовать временный файл, что также является отличным способом диагностики.
Если вы получаете «Ошибку формата потока», первым делом нужно проверить, что именно пришло в двоичных данных. Самый простой способ — сохранить их на диск и попробовать открыть вручную через «Файл - Открыть» в 1С.
Рассмотрим, как это реализовать:
ИмяФайла = ПолучитьИмяВременногоФайла("mxl");
ДвоичныеДанные = Base64Значение(СтрокаBase64);
ДвоичныеДанные.Записать(ИмяФайла);
// Теперь пробуем прочитать файл
ТабДок = Новый ТабличныйДокумент;
Попытка
ТабДок.Прочитать(ИмяФайла);
Сообщить("Файл успешно прочитан!");
Исключение
Сообщить("Ошибка чтения файла: " + ОписаниеОшибки());
КонецПопытки;
Если 1С не может открыть сохраненный файл вручную, значит, проблема в отправителе или в процессе передачи (кодирования) строки Base64. Для проверки структуры получаемых ответов и отправки тестовых запросов подойдёт консоль HTTP-запросов для управляемых форм.
Иногда разработчики сервисов используют системную сериализацию 1С. В этом случае данные — это не файл MXL, а «слепок» объекта. Метод Прочитать() здесь не поможет. Нам потребуется функция ЗначениеИзДвоичныхДанных().
Давайте посмотрим, как изменить код в этом случае:
ДвоичныеДанные = Base64Значение(СтрокаBase64);
Попытка
// Пытаемся восстановить объект напрямую
ОбъектРезультат = ЗначениеИзДвоичныхДанных(ДвоичныеДанные);
Если ТипЗнч(ОбъектРезультат) = Тип("ТабличныйДокумент") Тогда
ЭлементыФормы.ПолеТабличногоДокумента1.Вывести(ОбъектРезультат);
КонецЕсли;
Исключение
Сообщить("Данные не являются сериализованным объектом 1С");
КонецПопытки;
Часто проблема кроется в невидимых символах. При копировании строки из отладчика или при получении ее из JSON-пакета могут добавиться переносы строк. Перед обработкой рекомендуется «почистить» строку.
Разберем пример функции очистки:
// Убираем символы переноса строк и пробелы
ЧистаяСтрокаBase64 = СтрЗаменить(СтрокаBase64, Символы.ПС, "");
ЧистаяСтрокаBase64 = СтрЗаменить(ЧистаяСтрокаBase64, Символы.ВК, "");
ЧистаяСтрокаBase64 = СтрЗаменить(ЧистаяСтрокаBase64, " ", "");
ДвоичныеДанные = Base64Значение(ЧистаяСтрокаBase64);
Если вы имеете доступ к коду сервиса, который отправляет данные, убедитесь, что он формирует их правильно. Правильный способ формирования MXL для передачи в Base64 выглядит так:
Поток = Новый ПотокВПамяти();
// Записываем табличный документ в поток именно как MXL
ТабДок.Записать(Поток, ТипФайлаТабличногоДокумента.MXL);
ДвоичныеДанные = Поток.ЗакрытьИПолучитьДвоичныеДанные();
СтрокаДляОтправки = Base64Строка(ДвоичныеДанные);
Использование ХранилищеЗначения на стороне сервера также допустимо, но тогда на стороне клиента нужно будет сначала вызвать ЗначениеИзДвоичныхДанных(), чтобы получить само хранилище, а затем метод Получить() для извлечения табличного документа.
Подведем итоги. Если вы столкнулись с ошибкой формата потока при чтении табличного документа из Base64:
Записать() (нужно использовать Прочитать()) или через ЗначениеВДвоичныеДанные() (нужно использовать ЗначениеИзДвоичныхДанных()).Используя предложенные методы и примеры кода, вы сможете надежно реализовать передачу табличных отчетов между различными базами 1С и внешними приложениями.