При интеграции 1С с внешними веб-сервисами через HTTP-запросы часто возникает ситуация, когда в теле ответа приходит не чистый текст или JSON, а структура XML, где полезные данные упакованы в тег с типом base64Binary. На первый взгляд это кажется избыточным, но таков стандарт многих SOAP и REST-сервисов. В этой статье мы разберем, как элегантно извлечь эти данные, декодировать их и превратить в полноценный объект XML, не нагружая дисковую подсистему созданием временных файлов.
Рассмотрим ситуацию, когда после выполнения HTTPЗапрос мы получаем ответ, тело которого выглядит примерно так:
<base64Binary xmlns="http://tempuri.org/">PD94bWwgdmVyc2lvbj0iMS4wIj8+DQo8cmVzcG9uc2U+...</base64Binary>
Проблема заключается в том, что внутри XML-тега находится строка, закодированная по алгоритму Base64. Сама по себе эта строка — это «слепок» другого файла (в нашем случае — вложенного XML). Чтобы добраться до данных, нам нужно пройти три этапа:
base64Binary.ДвоичныеДанные.ЧтениеXML.Первым делом нам нужно получить саму зашифрованную строку. Если мы используем метод Ответ.ПолучитьТелоКакСтроку(), мы получим весь XML-контейнер. Чтобы достать только «начинку», проанализируем наиболее эффективные способы. Можно использовать строковые функции СтрНайти и Сред, но это ненадежно, если структура XML изменится. Правильнее использовать объект ЧтениеXML.
Рассмотрим пример кода для быстрого извлечения значения:
Чтение = Новый ЧтениеXML;
Чтение.УстановитьСтроку(ОтветHTTP.ПолучитьТелоКакСтроку());
Base64Строка = "";
Пока Чтение.Прочитать() Цикл
Если Чтение.ТипУзла = ТипУзлаXML.НачалоЭлемента И Чтение.Имя = "base64Binary" Тогда
Base64Строка = Чтение.ПрочитатьСодержимоеКакСтроку();
Прервать;
КонецЕсли;
КонецЦикла;
Использование метода ПрочитатьСодержимоеКакСтроку() позволяет нам сразу получить очищенные данные, находящиеся внутри тегов, игнорируя служебные символы XML.
Теперь, когда у нас есть «сырая» Base64-строка, воспользуемся встроенной функцией платформы Base64Значение(). Проанализируем, что она делает: она переводит текстовое представление байтов обратно в объект типа ДвоичныеДанные.
ДвоичныеДанныеДекодированные = Base64Значение(Base64Строка);
На этом этапе многие разработчики совершают ошибку, пытаясь сразу записать этот объект в файл. Но наша задача — избежать лишних операций с диском.
В старых версиях платформы 1С действительно было сложно обойтись без временного файла. Однако, начиная с версии 8.3.10, у нас есть мощный инструмент — метод ПолучитьСтрокуИзДвоичныхДанных(). Разберем, как его применить.
Выясним причину, почему важно указывать кодировку. XML внутри Base64 чаще всего закодирован в UTF-8. Если не указать это явно, система может использовать кодировку по умолчанию, что приведет к ошибке при попытке чтения XML-структуры.
// Преобразуем двоичные данные в обычную строку XML
СтрокаXML = ПолучитьСтрокуИзДвоичныхДанных(ДвоичныеДанныеДекодированные, КодировкаТекста.UTF8);
// Теперь загружаем эту строку в парсер
ЧтениеРезультата = Новый ЧтениеXML;
ЧтениеРезультата.УстановитьСтроку(СтрокаXML);
Пока ЧтениеРезультата.Прочитать() Цикл
// Здесь выполняем обход узлов полученного внутреннего XML
// Например: Если ЧтениеРезультата.Имя = "id" Тогда ...
КонецЦикла;
Если объем данных в base64Binary велик (например, выгрузка на несколько десятков мегабайт), преобразование в «тяжелую» строку может существенно замедлить работу и вызвать нехватку оперативной памяти. В современных версиях платформы (8.3.15 и выше) мы можем использовать потоки. Посмотрим на этот профессиональный метод:
// Создаем поток в памяти из полученных двоичных данных
Поток = Новый ПотокВПамяти(ДвоичныеДанныеДекодированные);
// Инициализируем чтение XML напрямую из потока
ЧтениеXMLПоток = Новый ЧтениеXML;
ЧтениеXMLПоток.ОткрытьПоток(Поток);
// Читаем данные привычным способом
Пока ЧтениеXMLПоток.Прочитать() Цикл
// Логика обработки данных
КонецЦикла;
ЧтениеXMLПоток.Закрыть();
Поток.Закрыть();
Этот способ является максимально производительным, так как данные передаются практически «напрямую» из бинарного вида в парсер, минуя стадию создания огромных текстовых строк в памяти.
Если у вас есть XSD-схема или вы работаете с типизированными данными, процесс можно еще больше автоматизировать. Тип xs:base64Binary — стандартный для XDTO. Разберем, как 1С работает с ним автоматически.
Если вы используете ФабрикаXDTO для чтения всего HTTP-ответа, то при наличии описания типа, платформа самостоятельно преобразует содержимое тега base64Binary в объект ДвоичныеДанные. Вам останется только выполнить декодирование строки из этих данных, как было показано выше.
При работе с Base64 и XML следует учитывать несколько критически важных моментов:
ЧтениеXML.УстановитьСтроку() выдает ошибку в первой позиции, попробуйте предварительно очистить строку или использовать метод с потоками, который лучше справляется с определением кодировки.Base64Значение() в 1С обычно игнорирует такие символы, но если вы получаете ошибку «Недопустимый символ», стоит проверить строку на наличие лишних пробелов с помощью СтрЗаменить(Стр, Символы.ПС, "").<?xml.Подведем итог: использование временных файлов для обработки Base64 — это пережиток прошлого. Используя ПолучитьСтрокуИзДвоичныхДанных или ПотокВПамяти, мы делаем наш код чище, быстрее и современнее. Проанализировав эти методы, вы сможете выбрать наиболее подходящий под ваши задачи и версию платформы.