Как программно отправить файл через HTTP POST запрос в 1С 8.3 (multipart/form-data)?

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

В современной практике интеграции 1С с внешними системами (мессенджерами, государственными порталами, веб-сайтами) часто возникает задача передачи файлов. Наиболее распространенным способом передачи бинарных данных является использование типа содержимого multipart/form-data. В рамках данной статьи мы подробно разберем, как реализовать этот механизм в 1С:Предприятии 8.3, проанализируем структуру запроса и изучим конкретные примеры кода.

Постановка задачи и анализ механизма

Когда нам необходимо передать файл через HTTPЗапрос, мы сталкиваемся с тем, что стандартные методы 1С требуют ручного формирования тела запроса, если сервер ожидает данные в формате формы. Основная сложность заключается в правильном формировании «границ» (boundary), которые отделяют текстовые поля запроса от содержимого файлов. Проанализируем типичную структуру такого сообщения:

  1. Установка уникального разделителя (Boundary).
  2. Формирование заголовка раздела для каждого параметра.
  3. Кодирование содержимого файла в бинарный поток.
  4. Завершение запроса финальным разделителем.

Шаг 1: Подготовка объекта HTTPСоединение

Прежде чем отправлять данные, нам необходимо инициализировать соединение с сервером. Разберем, какие параметры важны для стабильной работы. Рекомендуется всегда использовать явное указание таймаутов, чтобы избежать зависания сеанса при проблемах с сетью.


// Настройка параметров подключения
Сервер = "api.service.ru";
Порт = 443; // Для HTTPS
ИспользоватьSSL = Истина;

ЗащищенноеСоединение = Новый ЗащищенноеСоединениеOpenSSL();
Соединение = Новый HTTPСоединение(Сервер, Порт, , , , 30, ЗащищенноеСоединение);

Шаг 2: Формирование заголовков и Boundary

Рассмотрим подробнее работу с заголовками. Для multipart/form-data критически важно указать boundary в заголовке Content-Type. Разделитель должен быть уникальной строкой, которая точно не встретится внутри передаваемых данных.

Проанализируем пример создания уникальной границы:


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

Шаг 3: Сборка тела запроса (Binary Data)

Это самый ответственный этап. Мы не можем просто сложить строки, если передаем бинарный файл (например, PDF или картинку), так как неявное преобразование в строку может повредить кодировку файла. Мы будем использовать Поток или временные файлы для сборки данных.

Выясним причину использования ЗаписьДанных: этот объект позволяет записывать как текстовые фрагменты, так и двоичные данные в один поток без потери целостности.


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

// 1. Записываем начало раздела для файла
ЗаписьДанных.ЗаписатьСтроку("--" + Граница);
ЗаписьДанных.ЗаписатьСтроку("Content-Disposition: form-data; name=""file""; filename=""document.pdf""");
ЗаписьДанных.ЗаписатьСтроку("Content-Type: application/pdf"); // Указываем MIME-тип файла
ЗаписьДанных.ЗаписатьСтроку(""); // Пустая строка перед данными

// 2. Читаем файл и записываем его в поток
ДвоичныеДанныеФайла = Новый ДвоичныеДанные("C:\temp\document.pdf");
ЗаписьДанных.Записать(ДвоичныеДанныеФайла);

// 3. Записываем закрывающий разделитель
ЗаписьДанных.ЗаписатьСтроку("");
ЗаписьДанных.ЗаписатьСтроку("--" + Граница + "--");

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

Шаг 4: Отправка запроса и обработка ответа

Теперь, когда у нас есть сформированные заголовки и тело в виде ДвоичныеДанные, мы можем выполнить сам запрос. Посмотрим на пример вызова метода ОтправитьДляОбъекта или ВызватьHTTPМетод.


АдресРесурса = "/v1/upload";
Запрос = Новый HTTPЗапрос(АдресРесурса, Заголовки);
Запрос.УстановитьТелоИзДвоичныхДанных(РезультатТело);

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

Особенности работы с большими файлами

Рассмотрим ситуацию, когда объем передаваемого файла превышает несколько сотен мегабайт. В этом случае хранение всего тела запроса в оперативной памяти (через ПотокВПамяти) может привести к ошибке «Недостаточно памяти». Чтобы этого избежать, используем запись во временный файл на диске.

Разберем по шагам этот подход:

  1. Создаем временное имя файла через ПолучитьИмяВременногоФайла().
  2. Используем ЗаписьДанных с привязкой к этому файлу.
  3. После записи всех частей закрываем объект ЗаписьДанных.
  4. При создании HTTPЗапрос используем метод УстановитьТелоИзФайла().

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

Дополнительные параметры формы

Часто вместе с файлом нужно передать дополнительные метаданные (например, ID документа или комментарий). В формате multipart каждое такое поле оформляется как отдельная секция внутри границ.

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


// Добавление текстового поля 'comment'
ЗаписьДанных.ЗаписатьСтроку("--" + Граница);
ЗаписьДанных.ЗаписатьСтроку("Content-Disposition: form-data; name=""comment""");
ЗаписьДанных.ЗаписатьСтроку("");
ЗаписьДанных.ЗаписатьСтроку("Передача документа из 1С");

Заключение

Мы проанализировали процесс формирования HTTP-запроса для передачи бинарных данных. Ключевым моментом является строгое соблюдение структуры разделителей и использование объектов ЗаписьДанных и Поток для корректной работы с двоичными данными. Данный метод является универсальным и подходит для интеграции с большинством современных Web-API (Telegram, Slack, Bitrix24 и другие).

← На главную