Как извлечь и сохранить файл из HTTP-запроса multipart/form-data в 1С

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

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

Анализ проблемы: почему метод ПолучитьТелоКакДвоичныеДанные возвращает лишние данные

Рассмотрим типовую ситуацию. Сторонняя система отправляет POST-запрос с типом содержимого multipart/form-data, содержащий текстовые поля и файл. В обработчике HTTP-сервиса выполняется чтение тела:


ДвоичныеДанные = Запрос.ПолучитьТелоКакДвоичныеДанные();
ДвоичныеДанные.Записать("C:\temp\file.bin");

Открыв сохраненный файл, мы увидим не чистый двоичный поток, а весь HTTP-пакет целиком со служебными заголовками и разделителями:


--1BEF0A57BE110FD467A
Content-Disposition: form-data; name="usr"

Иванов Иван Иванович
--1BEF0A57BE110FD467A
Content-Disposition: form-data; name="File1"; filename="screen.png"
Content-Type: application/octet-stream
Content-Transfer-Encoding: binary

[Бинарные данные файла]
--1BEF0A57BE110FD467A--

Выясним причину такого поведения. В платформе 1С:Предприятие объект HTTPСервисЗапрос не содержит встроенного автоматического парсера составных частей multipart-запросов. Метод ПолучитьТелоКакДвоичныеДанные() возвращает «сырое» тело всего HTTP-пакета. Попытка преобразовать тело в строку через Запрос.ПолучитьТелоКакСтроку(), вырезать блок файла строковыми функциями и превратить его обратно в двоичные данные приводит к необратимому повреждению бинарных файлов (PNG, PDF, DOCX, ZIP), так как произвольные байты искажаются при перекодировании в символы UTF-8.

Вариант 1. Парсинг multipart/form-data штатными средствами платформы 1С

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

  1. Получение границы разделов: Из заголовка Content-Type входящего запроса извлекается параметр boundary, определяющий разделитель блоков.
  2. Инициализация потоков: На основе полученных двоичных данных запроса создаются объекты ПотокВПамяти и ЧтениеДанных.
  3. Поиск смещений: С помощью методов ЧтениеДанных.ПрочитатьДоМаркера() или через объект БуферДвоичныхДанных находятся байтовые маркеры границы (--boundary) и признак окончания служебных заголовков блока (последовательность байтов 0x0D 0x0A 0x0D 0x0A, соответствующая переводу строки \r\n\r\n).
  4. Извлечение файла: Байт-за-байтом или блоками данные между концом заголовков блока и следующим маркером границы считываются в результирующий поток, из которого затем формируются чистые ДвоичныеДанные.

Вариант 2. Изменение формата взаимодействия (рекомендуемый подход)

Если формат входящих запросов можно скорректировать на стороне клиента, задачу можно существенно упростить и сделать код более надежным и производительным. Рассмотрим архитектурные альтернативы:

Способ А. Передача параметров в HTTP-заголовках или URL, а файла — в теле запроса

Все метаданные (имя файла, автор, реквизиты) передаются в HTTP-заголовках запроса (Headers) или в строке параметров URL. Тело запроса отправляется с заголовком Content-Type: application/octet-stream и содержит исключительно бинарные данные файла. В таком случае в 1С код получения предельно прост:


// Читаем метаданные из заголовков
ИмяФайла = Запрос.Заголовки.Получить("X-File-Name");
Автор = Запрос.Заголовки.Получить("X-Author");

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

Способ Б. Передача через JSON с кодированием в Base64

Запрос формируется как JSON-документ, где реквизиты передаются обычными полями, а сам файл упакован в Base64-строку. В 1С разбор выполняется стандартными объектами:


ЧтениеJSON = Новый ЧтениеJSON;
ЧтениеJSON.УстановитьСтроку(Запрос.ПолучитьТелоКакСтроку());
ДанныеЗапроса = ПрочитатьJSON(ЧтениеJSON);
ЧтениеJSON.Закрыть();

// Извлекаем реквизиты и файл
ИмяФайла = ДанныеЗапроса.FileName;
ДвоичныеДанныеФайла = Base64Значение(ДанныеЗапроса.FileBase64);

Правильное сохранение файла в 1С:Документооборот

Когда чистые двоичные данные получены, их необходимо сохранить в базу. В конфигурации «1С:Документооборот» нельзя просто записать двоичные данные в ХранилищеЗначения справочника Файлы, так как система использует механизмы версионирования и может хранить файлы на внешних томах на диске.

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

  1. Помещаем полученные двоичные данные во временное хранилище с помощью метода ПоместитьВоВременноеХранилище().
  2. Используем экспортные методы подсистемы работы с файлами конфигурации (общие модули РаботаСФайлами или РаботаСФайламиСлужебный).
  3. Методы подсистемы автоматически создадут элементы справочников Файлы и ВерсииФайлов, вычислят размер, контрольную сумму (хеш) и сохранят физический файл на томе или в информационной базе в зависимости от действующих настроек.
← На главную