Как грамотно отправить PDF-файл из 1С через HTTP-запрос?

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

В процессе интеграции 1С с внешними веб-сервисами часто возникает задача передачи файлов, например, PDF-документов, хранящихся в базе. Несмотря на наличие встроенных механизмов работы с HTTP, разработчики часто сталкиваются с ситуацией, когда запрос уходит успешно (код 200), но принимающая сторона не может корректно прочитать файл. Разберем по шагам, как правильно организовать этот процесс, каких ошибок следует избегать и как оптимизировать передачу данных. Для предварительной отладки и проверки отправки HTTP-запросов можно использовать инструмент для тестирования REST API в 1С.

Анализ проблемы: почему файл не открывается на сервере?

Проанализируем типичную ситуацию: файл PDF получен из ХранилищеЗначения, преобразован в ДвоичныеДанные и отправлен как Base64-строка в теле POST-запроса. Если сервер возвращает успешный статус, но файл оказывается «битым», проблема чаще всего кроется в некорректной подготовке тела запроса или избыточных заголовках. Выясним основные причины:

  1. Лишние переносы строк в Base64. Метод 1С Base64Строка() по умолчанию может добавлять символы возврата каретки и перевода строки через каждые 72 символа. Если сервер не ожидает такого форматирования, декодирование пройдет с ошибкой.
  2. Неверный Content-Type. Указание text/plain вместо application/pdf (или наоборот, в зависимости от требований API) сбивает сервер с толку при интерпретации данных.
  3. Ручное управление Content-Length. Платформа 1С самостоятельно вычисляет размер тела запроса. Ручная установка этого заголовка может привести к несоответствию, если данные подвергались перекодированию.
  4. Избыточные заголовки сжатия. Указание Accept-Encoding: gzip без фактического сжатия данных со стороны 1С заставляет сервер ожидать архивированный поток.

Корректная подготовка и отправка данных в формате Base64

Рассмотрим рабочий пример кода, который решает проблему передачи файла через строку Base64. Этот метод подходит для небольших документов и простых API.


// Получаем двоичные данные из хранилища или файла
ДвоичныйФайл = СтрокаНабора.Файл.Получить(); 

// Преобразуем в Base64. Важно: для версий 8.3.10+ желательно 
// контролировать отсутствие переносов строк.
Строка64 = Base64Строка(ДвоичныйФайл);
// Если платформа старая, удаляем переносы вручную:
Строка64 = СтрЗаменить(СтрЗаменить(Строка64, Символы.ПС, ""), Символы.ВК, "");

Хост = "yyyy.yyy.kz";
АдресСтраницы = "/api/v1/upload/pdf";
МойТокен = "ваш_токен_авторизации";

// Настройка заголовков
Заголовки = Новый Соответствие();
// Указываем тип контента. Если сервер ждет «сырую» строку Base64, 
// иногда используется text/plain, но стандартом является application/pdf 
// при передаче бинарных данных.
Заголовки.Вставить("Content-Type", "text/plain"); 
Заголовки.Вставить("Authorization", "Bearer " + МойТокен);
Заголовки.Вставить("Accept-Encoding", "*/*");

ЗапросHTTP = Новый HTTPЗапрос(АдресСтраницы, Заголовки);
ЗапросHTTP.УстановитьТелоИзСтроки(Строка64);

// Настройка защищенного соединения
Соединение = Новый HTTPСоединение(Хост, 443, , , , , Новый ЗащищенноеСоединениеOpenSSL());

Попытка
    ОтветHTTP = Соединение.ОтправитьДляОбработки(ЗапросHTTP);
    Результат = ОтветHTTP.ПолучитьТелоКакСтроку();
    Сообщить("Ответ сервера: " + Результат);
Исключение
    Сообщить("Ошибка при отправке: " + ИнформацияОбОшибке().Описание);
КонецПопытки;

Оптимизация: передача через потоки (Streams)

Если PDF-документы имеют значительный размер (несколько мегабайт и выше), использование Base64 становится неэффективным. Это увеличивает объем передаваемого трафика на 33% и создает нагрузку на оперативную память сервера 1С. Проанализируем, как использовать Поток для прямой передачи бинарных данных.

Использование метода УстановитьТелоИзПотока() позволяет платформе считывать данные из файла или памяти и сразу отправлять их в сетевой сокет, не создавая гигантских строк в памяти. Рассмотрим этот подход:


// Предположим, файл уже записан во временный каталог
ИмяФайла = КаталогВременныхФайлов() + "document.pdf";
ДвоичныйФайл.Записать(ИмяФайла);

ФайловыйПоток = Новый ФайловыйПоток(ИмяФайла, РежимОткрытияФайла.Открыть);

ЗапросHTTP = Новый HTTPЗапрос(АдресСтраницы);
ЗапросHTTP.Заголовки.Вставить("Content-Type", "application/pdf");
ЗапросHTTP.Заголовки.Вставить("Authorization", "Bearer " + МойТокен);

// Устанавливаем тело напрямую из потока
ЗапросHTTP.УстановитьТелоИзПотока(ФайловыйПоток);

ОтветHTTP = Соединение.ОтправитьДляОбработки(ЗапросHTTP);
ФайловыйПоток.Закрыть(); // Не забываем закрывать потоки

Работа с форматом Multipart/form-data

Большинство современных веб-сервисов (написанных на PHP, Python, Java) ожидают файлы не в виде «сырого» тела запроса, а в формате multipart/form-data. Это стандарт, имитирующий отправку файла через HTML-форму. В 1С нет встроенного конструктора для этого формата, поэтому разберем структуру формирования такого запроса вручную.

Для этого нам необходимо создать Boundary (разделитель) и обернуть двоичные данные в специфическую текстовую оболочку. Посмотрим на примерную структуру тела такого запроса:


Разделитель = "----" + СтрЗаменить(Строка(Новый УникальныйИдентификатор), "-", "");
ТелоЗапроса = Новый ПотокВПамяти();
ЗаписьДанных = Новый ЗаписьДанных(ТелоЗапроса);

// Начало блока файла
ЗаписьДанных.ЗаписатьСтроку("--" + Разделитель);
ЗаписьДанных.ЗаписатьСтроку("Content-Disposition: form-data; name=""file""; filename=""document.pdf""");
ЗаписьДанных.ЗаписатьСтроку("Content-Type: application/pdf");
ЗаписьДанных.ЗаписатьСтроку(""); // Пустая строка перед данными

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

// Финализируем запрос
ЗаписьДанных = Новый ЗаписьДанных(ТелоЗапроса);
ЗаписьДанных.ЗаписатьСтроку("");
ЗаписьДанных.ЗаписатьСтроку("--" + Разделитель + "--");
ЗаписьДанных.Закрыть();

// Подготовка запроса
ЗапросHTTP = Новый HTTPЗапрос(АдресСтраницы);
ЗапросHTTP.Заголовки.Вставить("Content-Type", "multipart/form-data; boundary=" + Разделитель);
ЗапросHTTP.УстановитьТелоИзДвоичныхДанных(ТелоЗапроса.ЗакрытьИПолучитьДвоичныеДанные());

Важные рекомендации по безопасности и стабильности

Выясним еще несколько критических моментов, которые помогут избежать ошибок в промышленной эксплуатации:

Подводя итог, отметим, что выбор метода (Base64, бинарный поток или multipart) зависит исключительно от спецификации API принимающей стороны. Однако наиболее грамотным и универсальным с точки зрения производительности 1С является использование потоков и бинарной передачи данных без промежуточного кодирования в строку. Для практического освоения различных сценариев работы с HTTP и передачи файлов подойдёт интерактивный курс по работе с HTTP-запросами в 1С.

← На главную