Как правильно отправить файл .xlsx через HTTP-запрос в 1С: решаем проблему multipart/form-data

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

Передача файлов через API — одна из самых распространенных задач при интеграции 1С со сторонними сервисами. Однако формат multipart/form-data имеет множество скрытых нюансов, из-за которых сервер может возвращать ошибки вроде «Файл не найден» или «Некорректный формат данных», даже если визуально тело запроса выглядит правильно. Разберем по шагам, как сформировать корректный запрос, избежать проблем с кодировками и использовать современные возможности платформы 1С.

Проблема: почему API «не видит» файл?

Рассмотрим стандартную ситуацию: у нас есть рабочий пример на cURL, но при попытке реализовать его в 1С сервер выдает ошибку. Основные причины обычно скрываются в трех аспектах:

  1. Некорректные заголовки внутри тела: отсутствие пустых строк или кавычек в именах полей.
  2. Проблемы с кодировкой: наличие BOM (Byte Order Mark) в начале сообщения, который сбивает парсер сервера.
  3. Неправильные разделители строк: использование только Символы.ПС вместо стандартного для протокола HTTP CRLF (Символы.ВК + Символы.ПС).

Способ №1. Использование современных объектов платформы (8.3.18+)

Если ваша версия платформы позволяет, рекомендуем отказаться от ручного формирования текстовых файлов и строк. Начиная с версии 8.3.18, в 1С появился объект РазделениеДанныхВФорматеMultipartFormData, который берет на себя всю работу по расстановке границ (boundary) и формированию заголовков частей.

Проанализируем пример использования этого объекта:


// Создаем объект для формирования тела запроса
Разделитель = Новый РазделениеДанныхВФорматеMultipartFormData();

// Создаем часть с файлом
ЧастьФайла = Новый ЧастьДанныхВФорматеMultipartFormData();
ЧастьФайла.Заголовки.Вставить("Content-Disposition", "form-data; name=""file""; filename=""report.xlsx""");
ЧастьФайла.Заголовки.Вставить("Content-Type", "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");

// Устанавливаем тело из двоичных данных файла
ДвоичныеДанныеФайла = Новый ДвоичныеДанные("D:/report.xlsx");
ЧастьФайла.УстановитьТелоИзДвоичныхДанных(ДвоичныеДанныеФайла);

// Добавляем часть в общий поток
Разделитель.ДобавитьЧасть(ЧастьФайла);

// Получаем boundary и тело для запроса
Boundary = Разделитель.Граница;
ТелоЗапроса = Разделитель.ПолучитьТелоКакПоток();

// Формируем запрос
Заголовки = Новый Соответствие;
Заголовки.Вставить("Content-Type", "multipart/form-data; boundary=" + Boundary);
Запрос = Новый HTTPЗапрос("/api/v1/upload", Заголовки);
Запрос.УстановитьТелоИзПотока(ТелоЗапроса);

// Отправляем
Соединение = Новый HTTPСоединение("api.service.ru",,,, , , Новый ЗащищенноеСоединениеOpenSSL());
Ответ = Соединение.ОтправитьДляОбработки(Запрос);

Этот метод является наиболее надежным, так как платформа автоматически соблюдает стандарты RFC, включая правильные переносы строк и структуру границ.

Способ №2. Ручное формирование тела запроса (универсальный метод)

Если вы работаете на более старых версиях платформы, нам придется собрать тело запроса «вручную». Рассмотрим наиболее стабильный вариант — через объединение файлов. Это позволяет избежать проблем с памятью при передаче больших файлов и дает полный контроль над байтами.

Важный нюанс: Одной из главных причин ошибок является кодировка. При записи текста через ЗаписьТекста по умолчанию 1С добавляет BOM (специальные символы в начале файла). Многие веб-серверы (особенно на PHP/Python) не ожидают их увидеть в multipart и выдают ошибку. Чтобы этого избежать, при создании ЗаписьТекста необходимо явно указывать параметр ИспользоватьBOM как Ложь.

Разберем реализацию по шагам:


// 1. Подготовка переменных
Boundary = СтрЗаменить(Строка(Новый УникальныйИдентификатор), "-", "");
ИмяФайлаНачало = ПолучитьИмяВременногоФайла("txt");
ИмяФайлаКонец = ПолучитьИмяВременногоФайла("txt");
ПутьКФайлуЭксель = "D:/11111111_ACC.xlsx";

// 2. Формируем заголовочную часть
// Указываем КодировкаТекста.UTF8 и ПЯТЫЙ параметр Ложь (отключение BOM)
ЗаписьТекста = Новый ЗаписьТекста(ИмяФайлаНачало, КодировкаТекста.UTF8, Символы.ВК + Символы.ПС, Ложь, Ложь);
ЗаписьТекста.ЗаписатьСтроку("--" + Boundary);
// Важно: имя поля и имя файла должны быть в кавычках
ЗаписьТекста.ЗаписатьСтроку("Content-Disposition: form-data; name=""file""; filename=""data.xlsx""");
// Для .xlsx используем корректный MIME-тип
ЗаписьТекста.ЗаписатьСтроку("Content-Type: application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
ЗаписьТекста.ЗаписатьСтроку(""); // Обязательная пустая строка перед двоичными данными
ЗаписьТекста.Закрыть();

// 3. Формируем завершающую часть
ЗаписьТекста = Новый ЗаписьТекста(ИмяФайлаКонец, КодировкаТекста.UTF8, Символы.ВК + Символы.ПС, Ложь, Ложь);
ЗаписьТекста.ЗаписатьСтроку(""); // Перенос после двоичных данных
ЗаписьТекста.ЗаписатьСтроку("--" + Boundary + "--");
ЗаписьТекста.Закрыть();

// 4. Объединяем файлы в один финальный файл тела
ИмяФайлаТела = ПолучитьИмяВременногоФайла("post");
МассивФайлов = Новый Массив;
МассивФайлов.Добавить(ИмяФайлаНачало);
МассивФайлов.Добавить(ПутьКФайлуЭксель);
МассивФайлов.Добавить(ИмяФайлаКонец);
ОбъединитьФайлы(МассивФайлов, ИмяФайлаТела);

// 5. Отправка запроса
Заголовки = Новый Соответствие;
Заголовки.Вставить("Content-Type", "multipart/form-data; boundary=" + Boundary);
Запрос = Новый HTTPЗапрос("/api/endpoint", Заголовки);
Запрос.УстановитьИмяФайлаТела(ИмяФайлаТела);

// Результат
Ответ = Соединение.ОтправитьДляОбработки(Запрос);

Ключевые советы для успешной отладки

Проанализируем еще несколько важных моментов, которые помогут, если решение выше все равно не проходит проверку на стороне сервера:

  1. MIME-типы: Хотя для .xlsx стандартом является application/vnd.openxmlformats-officedocument.spreadsheetml.sheet, некоторые старые или специфические API могут требовать application/octet-stream или даже устаревший application/vnd.ms-excel. Попробуйте сменить тип, если сервер жалуется на формат.
  2. Путь к файлу: В заголовке filename старайтесь передавать только имя файла с расширением (например, "data.xlsx"), а не полный путь ("D:/files/data.xlsx"). Некоторые системы безопасности на стороне сервера блокируют запросы, содержащие абсолютные пути.
  3. Символы CRLF: Обратите внимание, что в протоколе HTTP стандартом переноса строки является \r\n. В 1С это сочетание Символы.ВК + Символы.ПС. При использовании ЗаписьТекста передавайте это сочетание в третий параметр конструктора.
  4. Проверка через перехватчик: Если API упорно не принимает файл, воспользуйтесь сервисами вроде webhook.site. Отправьте запрос из 1С туда и сравните полученный результат с рабочим запросом из Postman или cURL. Особое внимание уделите наличию лишних пробелов или невидимых символов в самом начале тела запроса.

Резюме: Основной секрет успеха при отправке .xlsx через 1С — это чистота бинарных данных. Использование ОбъединитьФайлы гарантирует, что сам файл Excel не будет поврежден при преобразовании в строку, а отключение BOM при записи текстовых заголовков сделает ваше сообщение понятным для любого веб-сервера.

← На главную