Как прочитать Табличный Документ из двоичных данных Base64: решение ошибки формата потока

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

В процессе интеграции 1С с внешними системами через HTTP-сервисы часто возникает задача передачи табличных документов. Наиболее распространенный формат передачи двоичных данных в текстовых протоколах (JSON, XML) — это кодировка Base64. Однако на стороне получателя разработчики нередко сталкиваются с ошибкой «Ошибка формата потока» при попытке преобразовать полученную строку обратно в ТабличныйДокумент. В этой статье мы подробно разберем, как правильно обрабатывать такие данные, проанализируем причины ошибок и рассмотрим рабочие примеры кода.

Суть проблемы и основные причины ошибки

Когда мы получаем строку Base64, которая должна содержать ТабличныйДокумент, мы выполняем стандартную последовательность действий: преобразуем строку в ДвоичныеДанные, открываем поток и вызываем метод Прочитать(). Если в этот момент возникает ошибка формата, это означает, что содержимое потока не соответствует ожиданиям метода Прочитать(). Рассмотрим основные причины этой ситуации:

  1. Разные методы упаковки: Отправитель мог использовать ЗначениеВДвоичныеДанные(), а получатель пытается использовать ТабДок.Прочитать(). Это принципиально разные механизмы: первый создает сериализованный объект 1С, второй ожидает файл формата MXL.
  2. Лишние символы в Base64: При передаче через HTTP в строку могут попасть символы переноса строк (CRLF), пробелы или BOM (Byte Order Mark), которые ломают структуру при декодировании.
  3. Некорректный формат файла: Сервис может возвращать данные в формате HTML, PDF или XLS, в то время как 1С по умолчанию пытается прочитать их как MXL.
  4. Двойное кодирование: Если данные передаются через XDTO с типом base64Binary, платформа может автоматически декодировать их в двоичные данные, и повторный вызов Base64Значение() приведет к порче данных.

Вариант 1. Чтение через поток (если передан файл MXL)

Если HTTP-сервис корректно сохранил табличный документ в поток в формате MXL, то на стороне клиента мы должны использовать метод ОткрытьПотокДляЧтения(). Давайте разберем этот алгоритм по шагам.

Проанализируем пример кода, который должен работать в большинстве стандартных случаев:


// Предположим, что СтрокаBase64 — это данные, полученные из сервиса
ДвоичныеДанные = Base64Значение(СтрокаBase64);

// Открываем поток для чтения из двоичных данных
Поток = ДвоичныеДанные.ОткрытьПотокДляЧтения();

ТабДок = Новый ТабличныйДокумент;
Попытка
    // Важно: можно явно указать формат файла, если вы в нем уверены
    ТабДок.Прочитать(Поток, ТипФайлаТабличногоДокумента.MXL);
    Поток.Закрыть();
    
    // Выводим результат в поле на форме
    ЭлементыФормы.ПолеТабличногоДокумента1.Вывести(ТабДок);
Исключение
    Поток.Закрыть();
    Сообщить("Не удалось прочитать документ: " + ОписаниеОшибки());
КонецПопытки;

Важный нюанс: Метод ОткрытьПотокДляЧтения() доступен в платформе 8.3. Если вы работаете на более старых версиях, вам придется использовать временный файл, что также является отличным способом диагностики.

Вариант 2. Использование временного файла для диагностики

Если вы получаете «Ошибку формата потока», первым делом нужно проверить, что именно пришло в двоичных данных. Самый простой способ — сохранить их на диск и попробовать открыть вручную через «Файл - Открыть» в 1С.

Рассмотрим, как это реализовать:


ИмяФайла = ПолучитьИмяВременногоФайла("mxl");
ДвоичныеДанные = Base64Значение(СтрокаBase64);
ДвоичныеДанные.Записать(ИмяФайла);

// Теперь пробуем прочитать файл
ТабДок = Новый ТабличныйДокумент;
Попытка
    ТабДок.Прочитать(ИмяФайла);
    Сообщить("Файл успешно прочитан!");
Исключение
    Сообщить("Ошибка чтения файла: " + ОписаниеОшибки());
КонецПопытки;

Если 1С не может открыть сохраненный файл вручную, значит, проблема в отправителе или в процессе передачи (кодирования) строки Base64. Для проверки структуры получаемых ответов и отправки тестовых запросов подойдёт консоль HTTP-запросов для управляемых форм.

Вариант 3. Восстановление через ЗначениеИзДвоичныхДанных

Иногда разработчики сервисов используют системную сериализацию 1С. В этом случае данные — это не файл MXL, а «слепок» объекта. Метод Прочитать() здесь не поможет. Нам потребуется функция ЗначениеИзДвоичныхДанных().

Давайте посмотрим, как изменить код в этом случае:


ДвоичныеДанные = Base64Значение(СтрокаBase64);

Попытка
    // Пытаемся восстановить объект напрямую
    ОбъектРезультат = ЗначениеИзДвоичныхДанных(ДвоичныеДанные);
    
    Если ТипЗнч(ОбъектРезультат) = Тип("ТабличныйДокумент") Тогда
        ЭлементыФормы.ПолеТабличногоДокумента1.Вывести(ОбъектРезультат);
    КонецЕсли;
Исключение
    Сообщить("Данные не являются сериализованным объектом 1С");
КонецПопытки;

Очистка строки Base64

Часто проблема кроется в невидимых символах. При копировании строки из отладчика или при получении ее из JSON-пакета могут добавиться переносы строк. Перед обработкой рекомендуется «почистить» строку.

Разберем пример функции очистки:


// Убираем символы переноса строк и пробелы
ЧистаяСтрокаBase64 = СтрЗаменить(СтрокаBase64, Символы.ПС, "");
ЧистаяСтрокаBase64 = СтрЗаменить(ЧистаяСтрокаBase64, Символы.ВК, "");
ЧистаяСтрокаBase64 = СтрЗаменить(ЧистаяСтрокаBase64, " ", "");

ДвоичныеДанные = Base64Значение(ЧистаяСтрокаBase64);

Проверка на стороне отправителя (HTTP-сервиса)

Если вы имеете доступ к коду сервиса, который отправляет данные, убедитесь, что он формирует их правильно. Правильный способ формирования MXL для передачи в Base64 выглядит так:


Поток = Новый ПотокВПамяти();
// Записываем табличный документ в поток именно как MXL
ТабДок.Записать(Поток, ТипФайлаТабличногоДокумента.MXL);
ДвоичныеДанные = Поток.ЗакрытьИПолучитьДвоичныеДанные();
СтрокаДляОтправки = Base64Строка(ДвоичныеДанные);

Использование ХранилищеЗначения на стороне сервера также допустимо, но тогда на стороне клиента нужно будет сначала вызвать ЗначениеИзДвоичныхДанных(), чтобы получить само хранилище, а затем метод Получить() для извлечения табличного документа.

Заключение

Подведем итоги. Если вы столкнулись с ошибкой формата потока при чтении табличного документа из Base64:

  1. Проверьте чистоту строки Base64 (отсутствие переносов строк).
  2. Попробуйте сохранить данные во временный файл и открыть его вручную для диагностики формата.
  3. Выясните, как именно данные упаковывались: через Записать() (нужно использовать Прочитать()) или через ЗначениеВДвоичныеДанные() (нужно использовать ЗначениеИзДвоичныхДанных()).
  4. Если используется современная платформа, всегда закрывайте потоки после использования для стабильной работы системы.

Используя предложенные методы и примеры кода, вы сможете надежно реализовать передачу табличных отчетов между различными базами 1С и внешними приложениями.

← На главную