При интеграции сторонних систем с 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.
Для корректного извлечения бинарного файла без искажений разбор необходимо выполнять исключительно на уровне байтов и потоков, не переводя все тело в строку. Разберем по шагам, как это реализовать:
Content-Type входящего запроса извлекается параметр boundary, определяющий разделитель блоков.ПотокВПамяти и ЧтениеДанных.ЧтениеДанных.ПрочитатьДоМаркера() или через объект БуферДвоичныхДанных находятся байтовые маркеры границы (--boundary) и признак окончания служебных заголовков блока (последовательность байтов 0x0D 0x0A 0x0D 0x0A, соответствующая переводу строки \r\n\r\n).ДвоичныеДанные.Если формат входящих запросов можно скорректировать на стороне клиента, задачу можно существенно упростить и сделать код более надежным и производительным. Рассмотрим архитектурные альтернативы:
Способ А. Передача параметров в 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С:Документооборот» нельзя просто записать двоичные данные в ХранилищеЗначения справочника Файлы, так как система использует механизмы версионирования и может хранить файлы на внешних томах на диске.
Разберем правильный порядок добавления файла программно:
ПоместитьВоВременноеХранилище().РаботаСФайлами или РаботаСФайламиСлужебный).Файлы и ВерсииФайлов, вычислят размер, контрольную сумму (хеш) и сохранят физический файл на томе или в информационной базе в зависимости от действующих настроек.