В практике интеграции 1С с веб-сервисами часто возникает задача передачи не только текстовых данных в формате JSON или XML, но и бинарных файлов, например, ZIP-архивов с выгрузками. Если для версии 1С 8.3 существуют встроенные средства работы с HTTP-запросами, то для старых версий (1С 7.7, 8.0, 8.1) или при специфических требованиях к окружению программисты часто прибегают к использованию COM-объектов MSXML2.XMLHTTP или WinHttp.WinHttpRequest.5.1. Рассмотрим подробно, как реализовать передачу ZIP-файла, какие объекты для этого потребуются и с какими нюансами можно столкнуться.
Самая простая ситуация — когда принимающая сторона (сайт) готова принять содержимое файла непосредственно из тела POST-запроса. В этом случае файл не упаковывается в специальную структуру формы (multipart/form-data), а передается «сырым» потоком байтов. Разберем, как это реализовать с помощью связки объектов ADODB.Stream и MSXML2.XMLHTTP.
Основная сложность в 1С (особенно в версии 7.7) заключается в том, что обычные строковые переменные не могут корректно хранить бинарные данные, так как нулевой байт воспринимается как конец строки. Для обхода этого ограничения мы будем использовать объект ADODB.Stream, который умеет работать с данными в двоичном виде.
Проанализируем программный код для реализации этой задачи:
// Определяем параметры подключения
АдресURL = "http://ваш-сайт.ru/api/upload";
ПутьКФайлу = "C:\export.zip";
// 1. Используем ADODB.Stream для чтения файла в бинарном виде
Поток = СоздатьОбъект("ADODB.Stream");
Поток.Type = 1; // 1 = adTypeBinary (важный момент!)
Поток.Open();
Поток.LoadFromFile(ПутьКФайлу);
// 2. Создаем объект для HTTP запроса
// Можно использовать MSXML2.XMLHTTP или MSXML2.ServerXMLHTTP для серверных скриптов
HTTPЗапрос = СоздатьОбъект("Msxml2.XMLHTTP");
HTTPЗапрос.Open("POST", АдресURL, 0); // 0 = синхронный запрос
// 3. Устанавливаем заголовки
HTTPЗапрос.setRequestHeader("Content-Type", "application/zip");
// 4. Отправляем бинарное содержимое потока
HTTPЗапрос.Send(Поток.Read());
// Проверяем результат
Если HTTPЗапрос.status = 200 Тогда
Сообщить("Файл успешно отправлен!");
Иначе
Сообщить("Ошибка отправки. Статус: " + HTTPЗапрос.status);
Сообщить("Ответ сервера: " + HTTPЗапрос.responseText);
КонецЕсли;
Поток.Close();
Важные моменты в этом коде:
Поток.Type = 1 обязательна. Это переводит объект в бинарный режим работы. По умолчанию используется текстовый режим, который повредит ZIP-архив.Поток.Read() возвращает массив байтов (SafeArray), который объект XMLHTTP понимает и корректно передает в теле запроса.Content-Type: application/zip сообщает серверу, что в теле запроса передается именно архив.Рассмотрим альтернативный вариант с использованием объекта WinHttp.WinHttpRequest.5.1. Этот объект считается более современным и гибким по сравнению с MSXML2.XMLHTTP. Проанализируем ситуацию: если передача файла занимает длительное время или требует работы через прокси-сервер, WinHttp справится лучше.
Выясним основные преимущества этого способа:
Пример реализации на WinHttp:
WinHttp = СоздатьОбъект("WinHttp.WinHttpRequest.5.1");
WinHttp.Open("POST", АдресURL, 0);
// Установка тайм-аутов: (Resolve, Connect, Send, Receive) в миллисекундах
WinHttp.SetTimeouts(30000, 30000, 60000, 60000);
WinHttp.SetRequestHeader("Content-Type", "application/zip");
// Читаем файл через ADODB.Stream, как в первом примере
Поток = СоздатьОбъект("ADODB.Stream");
Поток.Type = 1;
Поток.Open();
Поток.LoadFromFile(ПутьКФайлу);
WinHttp.Send(Поток.Read());
Сообщить("Статус: " + WinHttp.Status);
Разберем типичную проблему, с которой сталкиваются разработчики при общении с веб-администраторами. Часто администратор сайта говорит: «Я ничего не получил», хотя 1С возвращает статус 200. Причина кроется в том, как сервер ожидает данные.
Raw Data (Методы выше): Вы отправляете байты файла в «теле» (body) HTTP-запроса. На языке PHP, например, получить эти данные можно через file_get_contents('php://input'). В этом случае файл не будет виден в привычном массиве $_FILES.
Multipart/form-data: Это формат, имитирующий загрузку файла через HTML-форму браузером. В этом случае файл упаковывается в «конверт» с разделителями (boundary). Если сервер ожидает именно этот формат, то просто отправить бинарный поток через Send() будет недостаточно — сервер не сможет распознать начало и конец файла.
Для реализации multipart/form-data в 1С 7.7 или при использовании COM-объектов, вам придется вручную формировать «тело» запроса, склеивая заголовок формы, бинарные данные файла и закрывающий разделитель. Это сложная задача, требующая побайтового объединения через ADODB.Stream.
Если вы работаете на платформе 8.2 или 8.3, использование COM-объектов для этих целей считается избыточным. Посмотрим, как это решается штатными средствами платформы. Проанализируем использование объекта HTTPСоединение.
Начиная с версии 8.3.10, процесс стал максимально простым благодаря методу УстановитьТелоИзФайла объекта HTTPЗапрос. Это позволяет передавать файлы любого размера, не загружая их целиком в оперативную память 1С.
// Пример для 1С 8.3
Соединение = Новый HTTPСоединение("ваш-сайт.ru");
Запрос = Новый HTTPЗапрос("/api/upload");
Запрос.Заголовки.Вставить("Content-Type", "application/zip");
// Самый эффективный способ:
Запрос.УстановитьТелоИзФайла("C:\export.zip");
Ответ = Соединение.ОтправитьДляОбработки(Запрос);
Сообщить(Ответ.КодСостояния);
Рассмотрим причины, по которым отправка может не сработать:
php.ini параметры post_max_size и upload_max_filesize или в Nginx client_max_body_size) может стоять лимит, меньший, чем ваш ZIP-файл.WinHttp и увеличивайте время ожидания.URL Encode.Таким образом, для успешной отправки ZIP-файла из 1С с помощью MSXML2.XMLHTTP ключевым является использование ADODB.Stream для корректного чтения бинарных данных и правильная установка заголовков запроса. Если принимающая сторона требует сложный формат передачи (с именами полей и метаданными), стоит рассмотреть вариант передачи файла в строке Base64 внутри JSON-пакета, хотя это и увеличит объем трафика на 33%.