При интеграции 1С с современными веб-сервисами, такими как «Базис-Облако» или другими промышленными API, разработчики часто сталкиваются с необходимостью передачи данных в формате multipart/form-data. Особую сложность вызывают запросы типа PUT, где требуется не только передать файл или параметр, но и строго соблюсти структуру разделителей (boundaries) и кодировку. В этой статье мы подробно разберем, как правильно сформировать такой запрос, избежать ошибок авторизации и корректно передать параметры серверу.
Проанализируем ситуацию: автору необходимо изменить статус документа в стороннем сервисе. На первый взгляд, задача кажется тривиальной, но при реализации в 1С возникают следующие проблемы:
ОтправитьДляОбработки() в 1С по умолчанию инициирует POST-запрос. Если API ожидает PUT, сервер вернет ошибку 405 Method Not Allowed.multipart/form-data требует жесткого соблюдения синтаксиса разделителей, включая дефисы и пустые строки.Content-Type не указан параметр boundary, сервер не сможет разделить переданные данные на отдельные поля формы.Для начала нам необходимо создать объект Соответствие, в который мы поместим необходимые метаданные. Рассмотрим пример, где мы генерируем уникальный разделитель. Это критически важно, чтобы граница (boundary) не совпала с содержимым передаваемых данных.
Проанализируем код формирования заголовков:
ВремГраница = СтрЗаменить(Новый УникальныйИдентификатор, "-", "");
Заголовки = Новый Соответствие;
Заголовки.Вставить("apiKey", "Ваш_Ключ_API");
Заголовки.Вставить("accept", "application/json");
// Обязательно указываем boundary прямо в типе контента
Заголовки.Вставить("Content-Type", "multipart/form-data; boundary=" + ВремГраница);
Теперь рассмотрим, как правильно упаковать данные. Каждое поле в multipart/form-data начинается с разделителя, предваряемого двумя дефисами (--), за которыми следуют служебные заголовки поля и само значение. Выясним причину, по которой обычная склейка строк может не сработать: сервер ожидает строго определенные символы перевода строк — CRLF (Возврат каретки + Перевод строки).
Воспользуемся объектом ТекстовыйДокумент для удобной сборки тела:
ТелоЗапроса = Новый ТекстовыйДокумент;
// Устанавливаем правильный разделитель строк (CRLF)
ТелоЗапроса.РазделительСтрок = Символы.ВК + Символы.ПС;
// Начало блока параметра statusId
ТелоЗапроса.ДобавитьСтроку("--" + ВремГраница);
ТелоЗапроса.ДобавитьСтроку("Content-Disposition: form-data; name=""statusId""");
// Обязательная пустая строка перед значением
ТелоЗапроса.ДобавитьСтроку("");
ТелоЗапроса.ДобавитьСтроку("9"); // Значение статуса
// Финальный разделитель (с двумя дефисами в конце)
ТелоЗапроса.ДобавитьСтроку("--" + ВремГраница + "--");
ТелоЗапросаСтрока = ТелоЗапроса.ПолучитьТекст();
Ключевым моментом является передача строки в тело HTTP-запроса без лишних символов. Рассмотрим метод УстановитьТелоИзСтроки. Здесь крайне важно установить третий параметр в значение ИспользованиеByteOrderMark.НеИспользовать. Если этого не сделать, 1С добавит в начало потока символы, указывающие на порядок байтов, что для веб-сервера будет выглядеть как «мусор» перед первой границей разделителя.
Также важно использовать правильный метод объекта HTTPСоединение. Для выполнения PUT-запроса в 1С используется метод Записать() или ВызватьHTTPМетод().
Посмотрим на финальную реализацию отправки:
// Создаем запрос
HTTPЗапрос = Новый HTTPЗапрос("api-cutting-public/orders/" + IDДокумента + "/status", Заголовки);
// Устанавливаем тело без BOM
HTTPЗапрос.УстановитьТелоИзСтроки(ТелоЗапросаСтрока, КодировкаТекста.UTF8, ИспользованиеByteOrderMark.НеИспользовать);
// Настраиваем защищенное соединение
Соединение = Новый HTTPСоединение("cloud.bazissoft.ru", 443, , , , , Новый ЗащищенноеСоединениеOpenSSL());
Попытка
// Используем Записать() для выполнения метода PUT
HTTPОтвет = Соединение.Записать(HTTPЗапрос);
Сообщить("Код состояния: " + HTTPОтвет.КодСостояния);
Сообщить("Ответ сервера: " + HTTPОтвет.ПолучитьТелоКакСтроку());
Исключение
Сообщить("Ошибка при отправке запроса: " + ИнформацияОбОшибке().Описание);
КонецПопытки;
Давайте проанализируем, почему этот подход решает проблему. Во-первых, мы явно указали boundary в заголовках, что позволило парсеру сервера найти начало данных. Во-вторых, использование Символы.ВК + Символы.ПС обеспечило совместимость с требованиями протокола HTTP. В-третьих, отказ от JSON в пользу прямой передачи значения statusId в теле формы (как и ожидает формат multipart/form-data) устранил ошибку 400.
Важный совет: Если ваше API требует передачи нескольких полей, каждое из них должно быть отделено строкой --boundary, а завершаться вся конструкция должна строкой --boundary--. Никогда не забывайте про пустую строку после заголовка Content-Disposition внутри тела — это стандарт, без которого данные не будут прочитаны корректно.
Таким образом, комбинируя правильное управление потоками данных, контроль кодировок и корректные HTTP-методы, можно успешно интегрировать 1С с любыми современными облачными сервисами.