В современной практике интеграции 1С с внешними системами (мессенджерами, государственными порталами, веб-сайтами) часто возникает задача передачи файлов. Наиболее распространенным способом передачи бинарных данных является использование типа содержимого multipart/form-data. В рамках данной статьи мы подробно разберем, как реализовать этот механизм в 1С:Предприятии 8.3, проанализируем структуру запроса и изучим конкретные примеры кода.
Когда нам необходимо передать файл через HTTPЗапрос, мы сталкиваемся с тем, что стандартные методы 1С требуют ручного формирования тела запроса, если сервер ожидает данные в формате формы. Основная сложность заключается в правильном формировании «границ» (boundary), которые отделяют текстовые поля запроса от содержимого файлов. Проанализируем типичную структуру такого сообщения:
Прежде чем отправлять данные, нам необходимо инициализировать соединение с сервером. Разберем, какие параметры важны для стабильной работы. Рекомендуется всегда использовать явное указание таймаутов, чтобы избежать зависания сеанса при проблемах с сетью.
// Настройка параметров подключения
Сервер = "api.service.ru";
Порт = 443; // Для HTTPS
ИспользоватьSSL = Истина;
ЗащищенноеСоединение = Новый ЗащищенноеСоединениеOpenSSL();
Соединение = Новый HTTPСоединение(Сервер, Порт, , , , 30, ЗащищенноеСоединение);
Рассмотрим подробнее работу с заголовками. Для multipart/form-data критически важно указать boundary в заголовке Content-Type. Разделитель должен быть уникальной строкой, которая точно не встретится внутри передаваемых данных.
Проанализируем пример создания уникальной границы:
Граница = "----" + СтрЗаменить(Строка(Новый УникальныйИдентификатор()), "-", "");
Заголовки = Новый Соответствие;
Заголовки.Вставить("Content-Type", "multipart/form-data; boundary=" + Граница);
Это самый ответственный этап. Мы не можем просто сложить строки, если передаем бинарный файл (например, PDF или картинку), так как неявное преобразование в строку может повредить кодировку файла. Мы будем использовать Поток или временные файлы для сборки данных.
Выясним причину использования ЗаписьДанных: этот объект позволяет записывать как текстовые фрагменты, так и двоичные данные в один поток без потери целостности.
// Создаем поток в памяти для формирования тела
ПотокТела = Новый ПотокВПамяти();
ЗаписьДанных = Новый ЗаписьДанных(ПотокТела);
// 1. Записываем начало раздела для файла
ЗаписьДанных.ЗаписатьСтроку("--" + Граница);
ЗаписьДанных.ЗаписатьСтроку("Content-Disposition: form-data; name=""file""; filename=""document.pdf""");
ЗаписьДанных.ЗаписатьСтроку("Content-Type: application/pdf"); // Указываем MIME-тип файла
ЗаписьДанных.ЗаписатьСтроку(""); // Пустая строка перед данными
// 2. Читаем файл и записываем его в поток
ДвоичныеДанныеФайла = Новый ДвоичныеДанные("C:\temp\document.pdf");
ЗаписьДанных.Записать(ДвоичныеДанныеФайла);
// 3. Записываем закрывающий разделитель
ЗаписьДанных.ЗаписатьСтроку("");
ЗаписьДанных.ЗаписатьСтроку("--" + Граница + "--");
ЗаписьДанных.Закрыть();
РезультатТело = ПотокТела.ЗакрытьИПолучитьДвоичныеДанные();
Теперь, когда у нас есть сформированные заголовки и тело в виде ДвоичныеДанные, мы можем выполнить сам запрос. Посмотрим на пример вызова метода ОтправитьДляОбъекта или ВызватьHTTPМетод.
АдресРесурса = "/v1/upload";
Запрос = Новый HTTPЗапрос(АдресРесурса, Заголовки);
Запрос.УстановитьТелоИзДвоичныхДанных(РезультатТело);
Попытка
Ответ = Соединение.ОтправитьДляОбъекта(Запрос);
Если Ответ.КодСостояния = 200 Тогда
Сообщить("Файл успешно отправлен!");
ПроанализируемОтвет(Ответ.ПолучитьТелоКакСтроку());
Иначе
Сообщить("Ошибка сервера: " + Ответ.КодСостояния);
КонецЕсли;
Исключение
Сообщить("Ошибка связи: " + ОписаниеОшибки());
КонецПопытки;
Рассмотрим ситуацию, когда объем передаваемого файла превышает несколько сотен мегабайт. В этом случае хранение всего тела запроса в оперативной памяти (через ПотокВПамяти) может привести к ошибке «Недостаточно памяти». Чтобы этого избежать, используем запись во временный файл на диске.
Разберем по шагам этот подход:
ПолучитьИмяВременногоФайла().ЗаписьДанных с привязкой к этому файлу.ЗаписьДанных.HTTPЗапрос используем метод УстановитьТелоИзФайла().Важно: После отправки запроса не забудьте удалить временный файл с диска, чтобы не засорять систему.
Часто вместе с файлом нужно передать дополнительные метаданные (например, ID документа или комментарий). В формате multipart каждое такое поле оформляется как отдельная секция внутри границ.
Посмотрим на пример добавления текстового поля:
// Добавление текстового поля 'comment'
ЗаписьДанных.ЗаписатьСтроку("--" + Граница);
ЗаписьДанных.ЗаписатьСтроку("Content-Disposition: form-data; name=""comment""");
ЗаписьДанных.ЗаписатьСтроку("");
ЗаписьДанных.ЗаписатьСтроку("Передача документа из 1С");
Мы проанализировали процесс формирования HTTP-запроса для передачи бинарных данных. Ключевым моментом является строгое соблюдение структуры разделителей и использование объектов ЗаписьДанных и Поток для корректной работы с двоичными данными. Данный метод является универсальным и подходит для интеграции с большинством современных Web-API (Telegram, Slack, Bitrix24 и другие).