Как отправить ZIP-файл в формате base64Binary через веб-сервис в 1С

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

При интеграции 1С со сторонними SOAP-сервисами часто возникает необходимость отправки файлов, упакованных в ZIP-архив и закодированных в формат base64Binary. Разберем типичные проблемы, с которыми сталкиваются разработчики при работе с механизмом WSПрокси и объектами XDTO, а также рассмотрим готовые способы решения этой задачи.

Причины возникновения проблем при передаче base64Binary

Рассмотрим, почему при попытке передать закодированный файл свойству объекта XDTO может возникать ошибка и сервис отказывается принимать данные:

  1. Особенности сериализации типов XDTO: В платформе 1С типу XML Schema xs:base64Binary из пространства имен http://www.w3.org/2001/XMLSchema напрямую соответствует объект встроенного языка ДвоичныеДанные. Если присвоить свойству XDTO с типом base64Binary обычную текстовую строку (даже закодированную через Base64Строка()), механизм сериализации 1С может некорректно ее обработать или повторно задирать в Base64.
  2. Символы переноса строк: Функция Base64Строка() при кодировании бинарного файла автоматически разбивает итоговый текст на строки, добавляя символы перевода строки (\r\n или \n). Многие сторонние веб-сервисы валидируют входящий поток строго и выдают ошибку при наличии таких переносов внутри Base64-контента.
  3. Специфические SOAP-заголовки: Веб-сервисы часто требуют передачи дополнительных заголовков авторизации (например, SOAP Header / WS-Security). Стандартный объект WSПрокси не всегда позволяет гибко настроить произвольные XML-заголовки.

Вариант 1. Использование объекта ДвоичныеДанные и Фабрики XDTO

Проанализируем правильный подход к работе через WSПрокси. Для свойств объектов XDTO, имеющих тип base64Binary, не требуется ручное кодирование через Base64Строка(). Достаточно передать объект ДвоичныеДанные напрямую:


ПутьКФайлу = "C:\zip_data.zip";
ДвоичныеДанныеФайла = Новый ДвоичныеДанные(ПутьКФайлу);

// Прямое присвоение объекта ДвоичныеДанные свойству XDTO
Объект.zippedXML = ДвоичныеДанныеФайла;
Объект.schemaId = 3;

ОтветСервера = Прокси.UploadZippedData2(Объект);

Если в схеме сервиса используется явная фабрика типов, можно сформировать лексическое значение с помощью вызова ФабрикаXDTO.Создать():


Типbase64Binary = ФабрикаXDTO.Тип("http://www.w3.org/2001/XMLSchema", "base64Binary");
ДвоичныеДанныеФайла = Новый ДвоичныеДанные(ПутьКФайлу);

// Создаем объект XDTO и берем его лексическое представление
ДанныеBase64 = ФабрикаXDTO.Создать(Типbase64Binary, ДвоичныеДанныеФайла).ЛексическоеЗначение;
Объект.zippedXML = ДанныеBase64;

Вариант 2. Прямая отправка SOAP-запроса через HTTPСоединение

Разберем случай, когда нужно передавать авторизационные заголовки в SOAP-конверте или очищать текстовую строку от лишних спецсимволов. В таком случае надежнее сформировать XML-тело запроса вручную и отправить его с помощью объектов HTTPСоединение и HTTPЗапрос.

Выясним по шагам порядок действий:

  1. Загружаем файл архива в объект ДвоичныеДанные.
  2. Преобразуем двоичные данные в строку Base64 через Base64Строка().
  3. Удаляем из полученной строки все символы перевода строки Символы.ПС и Символы.ВК.
  4. Формируем текст SOAP-конверта с нужной структурой и заголовками.
  5. Выполняем POST-запрос к веб-сервису через HTTPСоединение.

Посмотрим на пример кода реализации данного способа:


ПутьКФайлу = "C:\zip_data.zip";
ДвоичныйZIP = Новый ДвоичныеДанные(ПутьКФайлу);

// Получение Base64-строки и очистка от переносов строк
СтрокаBase64 = Base64Строка(ДвоичныйZIP);
СтрокаBase64 = СтрЗаменить(СтрЗаменить(СтрокаBase64, Символы.ПС, ""), Символы.ВК, "");

Пользователь = "User1C";
Пароль = "SecretPassword";

// Формирование XML-структуры SOAP-конверта
ТекстЗапроса = "<?xml version=""1.0"" encoding=""utf-8""?>
|<soap:Envelope xmlns:xsi=""http://www.w3.org/2001/XMLSchema-instance"" 
|               xmlns:xsd=""http://www.w3.org/2001/XMLSchema"" 
|               xmlns:soap=""http://schemas.xmlsoap.org/soap/envelope/"">
|  <soap:Header>
|    <AuthHeader xmlns=""http://example.org/DataPumpService"">
|      <Username>" + Пользователь + "</Username>
|      <Password>" + Пароль + "</Password>
|    </AuthHeader>
|  </soap:Header>
|  <soap:Body>
|    <UploadZippedData2 xmlns=""http://example.org/DataPumpService"">
|      <zippedXML>" + СтрокаBase64 + "</zippedXML>
|      <schemaId>3</schemaId>
|    </UploadZippedData2>
|  </soap:Body>
|</soap:Envelope>";

// Настройка HTTP-соединения
Сервер = "example.org";
Ресурс = "/DataPumpService.asmx";

HTTPСоединение = Новый HTTPСоединение(Сервер);

HTTPЗапрос = Новый HTTPЗапрос(Ресурс);
HTTPЗапрос.Заголовки.Вставить("Content-Type", "text/xml; charset=utf-8");
HTTPЗапрос.Заголовки.Вставить("SOAPAction", "http://example.org/DataPumpService/UploadZippedData2");
HTTPЗапрос.УстановитьТелоИзСтроки(ТекстЗапроса, КодировкаТекста.UTF8);

// Отправка запроса
ОтветHTTP = HTTPСоединение.ОтправитьДляОбработки(HTTPЗапрос);
КодСостояния = ОтветHTTP.КодСостояния;
ТекстОтвета = ОтветHTTP.ПолучитьТелоКакСтроку();

Использование HTTPСоединение дает вам полный контроль над отправляемыми заголовками, кодировкой и содержимым тело запроса, позволяя гарантированно передавать архивированные данные в сторонние системы.

← На главную