Как передать параметры и файлы в POST-запросе в 1С:Предприятие

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

При интеграции 1С с внешними веб-сервисами, интернет-магазинами, государственными информационными системами или сторонними API разработчики постоянно сталкиваются с необходимостью отправки POST-запросов. В отличие от GET-запросов, где параметры чаще всего передаются непосредственно в строке адреса (URL), POST-запросы предполагают передачу данных в теле запроса (Request Body). Это могут быть структурированные данные JSON/XML, бинарные файлы или сложные формы формата multipart/form-data.

В этой статье мы подробно разберем все аспекты работы с POST-запросами в 1С. Мы изучим как базовые сценарии (передачу JSON-параметров и файлов), так и профессиональные подходы, актуальные для современных версий платформы 1С:Предприятие 8.3, включая работу с асинхронными методами и потоками данных.

Шаг 1. Инициализация HTTP-соединения и создание запроса

Прежде чем наполнять запрос данными, нам необходимо правильно настроить базовые объекты: HTTPСоединение и HTTPЗапрос. Для обеспечения безопасности в современном веб-пространстве практически всегда используется защищенное соединение (HTTPS), требующее использования объекта ЗащищенноеСоединениеOpenSSL.

Рассмотрим пример инициализации базовых объектов и установки заголовков:


// Создаем защищенное соединение для работы по протоколу HTTPS
ЗащищенноеСоединение = Новый ЗащищенноеСоединениеOpenSSL;
Соединение = Новый HTTPСоединение("api.myservice.ru", 443, , , , , ЗащищенноеСоединение);

// Определяем заголовки запроса
Заголовки = Новый Соответствие;
Заголовки.Вставить("Content-Type", "application/json; charset=UTF-8");
Заголовки.Вставить("Accept", "application/json");

// Создаем объект запроса с указанием относительного пути (URI) и заголовков
Запрос = Новый HTTPЗапрос("/api/v1/users", Заголовки);

Обратите внимание на заголовок Content-Type. Он сообщает серверу, в каком формате мы передаем данные в теле запроса. В данном примере мы указали application/json, что является стандартом де-факто для современных REST API.

Шаг 2. Передача параметров в формате JSON через тело запроса

Для передачи параметров (например, ID пользователя, статуса, настроек) в теле запроса используется метод УстановитьТелоИзСтроки(). Однако ручное формирование JSON-строки чревато синтаксическими ошибками. Правильным подходом является сериализация объектов 1С (таких как Структура или Соответствие) с помощью встроенных механизмов работы с JSON.

Разберем правильный и надежный способ подготовки параметров:


// Формируем параметры запроса в виде привычной структуры 1С
ПараметрыЗапроса = Новый Структура;
ПараметрыЗапроса.Вставить("id", 10254);
ПараметрыЗапроса.Вставить("status", "active");
ПараметрыЗапроса.Вставить("email", "user@example.com");

// Сериализуем структуру в строку JSON
ЗаписьJSON = Новый ЗаписьJSON;
ЗаписьJSON.УстановитьСтроку();
ЗаписатьJSON(ЗаписьJSON, ПараметрыЗапроса);
СтрокаТелаЗапроса = ЗаписьJSON.Закрыть();

// Устанавливаем сформированную строку в тело запроса
Запрос.УстановитьТелоИзСтроки(СтрокаТелаЗапроса, КодировкаТекста.UTF8, ИспользованиеByteOrderMark.НеИспользовать);

Важная деталь: При вызове метода УстановитьТелоИзСтроки крайне важно использовать параметр ИспользованиеByteOrderMark.НеИспользовать. Если этого не сделать, 1С может добавить маркер последовательности байтов (BOM) в начало строки, из-за чего многие веб-серверы не смогут корректно распарсить входящий JSON и вернут ошибку HTTP 400 Bad Request.

Шаг 3. Передача файлов в теле запроса

Часто перед разработчиком встает задача отправить файл (изображение, PDF-документ, XML-выгрузку) на сервер. В платформе 1С реализовано несколько способов решения этой задачи в зависимости от размера передаваемых файлов.

Вариант А. Использование метода УстановитьИмяФайлаТела (Оптимально для больших файлов)

Если файл имеет большой размер (от нескольких мегабайт до гигабайт), загрузка его целиком в оперативную память может привести к перерасходу ресурсов сервера 1С или аварийному завершению работы процесса. Метод УстановитьИмяФайлаТела() позволяет платформе считывать данные напрямую с жесткого диска и порционно транслировать их в сетевой сокет.


ПутьКФайлу = "C:\temp\huge_report.pdf";

// Указываем платформе путь к файлу, который будет отправлен в теле запроса
Запрос.УстановитьИмяФайлаТела(ПутьКФайлу);

// В заголовках запроса рекомендуется указать соответствующий MIME-тип
Запрос.Заголовки.Вставить("Content-Type", "application/pdf");

Вариант Б. Отправка через двоичные данные

Если файл небольшой и вы уже работаете с ним в памяти в виде объекта ДвоичныеДанные, можно использовать метод УстановитьТелоИзДвоичныхДанных():


ДвоичныеДанныеФайла = Новый ДвоичныеДанные("C:\temp\small_icon.png");
Запрос.УстановитьТелоИзДвоичныхДанных(ДвоичныеДанныеФайла);
Запрос.Заголовки.Вставить("Content-Type", "image/png");

Шаг 4. Сложный сценарий: Одновременная отправка параметров и файлов (формат multipart/form-data)

Бывают ситуации, когда веб-сервис требует передать и текстовые параметры (например, ID папки, описание файла), и сам файл в рамках одного POST-запроса. Стандартный JSON в этом случае не подходит — используется кодирование multipart/form-data. Этот формат предполагает разделение данных специальной уникальной границей (boundary).

Начиная с версии 8.3.9, формировать такое тело запроса удобнее всего в оперативной памяти через потоки данных, избегая создания лишних временных файлов на диске:


// Определяем уникальный разделитель (boundary)
Разделитель = "----1CBoundary" + СтрЗаменить(Строка(Новый УникальныйИдентификатор), "-", "");

// Указываем тип контента с границей в заголовках запроса
Запрос.Заголовки.Вставить("Content-Type", "multipart/form-data; boundary=" + Разделитель);

// Создаем поток в памяти для формирования тела запроса
ПотокТела = Новый ПотокВПамяти;
ЗаписьДанных = Новый ЗаписьДанных(ПотокТела, КодировкаТекста.UTF8);

// 1. Записываем текстовый параметр "folder_id"
ЗаписьДанных.ЗаписатьСтроку("--" + Разделитель);
ЗаписьДанных.ЗаписатьСтроку("Content-Disposition: form-data; name=""folder_id""");
ЗаписьДанных.ЗаписатьСтроку(""); // Обязательная пустая строка перед значением
ЗаписьДанных.ЗаписатьСтроку("9985"); // Значение параметра

// 2. Добавляем секцию для файла
ДвоичныеДанныеФайла = Новый ДвоичныеДанные("C:\temp\document.docx");

ЗаписьДанных.ЗаписатьСтроку("--" + Разделитель);
ЗаписьДанных.ЗаписатьСтроку("Content-Disposition: form-data; name=""file""; filename=""document.docx""");
ЗаписьДанных.ЗаписатьСтроку("Content-Type: application/vnd.openxmlformats-officedocument.wordprocessingml.document");
ЗаписьДанных.ЗаписатьСтроку(""); // Обязательная пустая строка перед бинарными данными

// Сбрасываем буфер записи текста перед записью бинарных данных
ЗаписьДанных.СброситьБуфер();

// Записываем бинарные данные файла в поток тела запроса
ПотокТела.Записать(ДвоичныеДанныеФайла);

// Завершаем тело запроса финальной границей
ЗаписьДанных.ЗаписатьСтроку("");
ЗаписьДанных.ЗаписатьСтроку("--" + Разделитель + "--");
ЗаписьДанных.СброситьБуфер();

// Получаем результирующие двоичные данные из потока и помещаем их в запрос
ДвоичныеДанныеТела = ПотокТела.ЗакрытьИПолучитьДвоичныеДанные();
Запрос.УстановитьТелоИзДвоичныхДанных(ДвоичныеДанныеТела);

Шаг 5. Отправка запроса: Современный подход и асинхронность

После того как тело запроса полностью сформировано, его необходимо отправить на сервер. Исторически для отправки POST-запросов применялся метод ОтправитьДляОбработки(). Однако в современной разработке на платформе 1С произошли важные изменения, о которых обязан знать каждый разработчик.

  1. Переход на универсальный метод ВызватьHTTPМетод(): Вместо устаревших специализированных методов (таких как ОтправитьДляОбработки или Записать) рекомендуется использовать метод ВызватьHTTPМетод(). Он делает код более понятным, так как тип HTTP-метода ("POST", "PUT", "DELETE", "PATCH") явно передается в качестве первого аргумента.
  2. Требование асинхронности (начиная с 1С 8.3.21): Если вы отправляете HTTP-запрос непосредственно из кода клиентского приложения (в тонком или веб-клиенте), использование синхронных методов заблокирует интерфейс пользователя. Начиная с версии платформы 8.3.21, синхронные методы работы с сетью на клиенте объявлены устаревшими и вызывают предупреждения компилятора. Необходимо использовать их асинхронные аналоги.

Пример отправки запроса на сервере (синхронный вызов):


Попытка
    // Используем универсальный метод ВызватьHTTPМетод вместо ОтправитьДляОбработки
    Ответ = Соединение.ВызватьHTTPМетод("POST", Запрос);
    
    Если Ответ.КодСостояния = 200 Или Ответ.КодСостояния = 201 Тогда
        Сообщить("Данные успешно отправлены! Ответ сервера: " + Ответ.ПолучитьТелоКакСтроку());
    Иначе
        ВызватьИсключение "Сервер вернул код ошибки: " + Ответ.КодСостояния;
    КонецЕсли;
Исключение
    ЗаписьЖурналаРегистрации("Интеграция.ВыгрузкаДанных", УровеньЖурналаРегистрации.Ошибка, , , ПодробноеПредставлениеОшибки(ИнформацияОбОшибке()));
    ВызватьИсключение "Не удалось связаться с сервером. Подробности записаны в журнал регистрации.";
КонецПопытки;

Пример отправки запроса на клиенте (асинхронный вызов для 1С 8.3.21+):


&НаКлиенте
Асинх Процедура ОтправитьДанныеНаКлиенте()
    
    ЗащищенноеСоединение = Новый ЗащищенноеСоединениеOpenSSL;
    Соединение = Новый HTTPСоединение("api.myservice.ru", 443, , , , , ЗащищенноеСоединение);
    
    Запрос = Новый HTTPЗапрос("/api/v1/data");
    Запрос.УстановитьТелоИзСтроки("{""param"":""value""}", КодировкаТекста.UTF8, ИспользованиеByteOrderMark.НеИспользовать);
    
    Попытка
        // Асинхронное ожидание выполнения сетевой операции без замораживания интерфейса
        Ответ = Ждать Соединение.ВызватьHTTPМетодАсинх("POST", Запрос);
        
        Если Ответ.КодСостояния = 200 Тогда
            ПоказатьПредупреждение(, "Данные успешно отправлены!");
        КонецЕсли;
    Исключение
        ПоказатьПредупреждение(, "Произошла ошибка при отправке данных: " + КраткоеПредставлениеОшибки(ИнформацияОбОшибке()));
    КонецПопытки;
    
КонецПроцедуры

Использование конструкции Ждать и директивы Асинх позволяет писать лаконичный и читаемый код, который при этом работает асинхронно, обеспечивая плавность работы интерфейса вашей конфигурации 1С.

← На главную