В процессе интеграции 1С с внешними веб-сервисами часто возникает задача передачи файлов, например, PDF-документов, хранящихся в базе. Несмотря на наличие встроенных механизмов работы с HTTP, разработчики часто сталкиваются с ситуацией, когда запрос уходит успешно (код 200), но принимающая сторона не может корректно прочитать файл. Разберем по шагам, как правильно организовать этот процесс, каких ошибок следует избегать и как оптимизировать передачу данных. Для предварительной отладки и проверки отправки HTTP-запросов можно использовать инструмент для тестирования REST API в 1С.
Проанализируем типичную ситуацию: файл PDF получен из ХранилищеЗначения, преобразован в ДвоичныеДанные и отправлен как Base64-строка в теле POST-запроса. Если сервер возвращает успешный статус, но файл оказывается «битым», проблема чаще всего кроется в некорректной подготовке тела запроса или избыточных заголовках. Выясним основные причины:
Base64Строка() по умолчанию может добавлять символы возврата каретки и перевода строки через каждые 72 символа. Если сервер не ожидает такого форматирования, декодирование пройдет с ошибкой.text/plain вместо application/pdf (или наоборот, в зависимости от требований API) сбивает сервер с толку при интерпретации данных.Accept-Encoding: gzip без фактического сжатия данных со стороны 1С заставляет сервер ожидать архивированный поток.Рассмотрим рабочий пример кода, который решает проблему передачи файла через строку 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.ПолучитьТелоКакСтроку();
Сообщить("Ответ сервера: " + Результат);
Исключение
Сообщить("Ошибка при отправке: " + ИнформацияОбОшибке().Описание);
КонецПопытки;
Если PDF-документы имеют значительный размер (несколько мегабайт и выше), использование Base64 становится неэффективным. Это увеличивает объем передаваемого трафика на 33% и создает нагрузку на оперативную память сервера 1С. Проанализируем, как использовать Поток для прямой передачи бинарных данных.
Использование метода УстановитьТелоИзПотока() позволяет платформе считывать данные из файла или памяти и сразу отправлять их в сетевой сокет, не создавая гигантских строк в памяти. Рассмотрим этот подход:
// Предположим, файл уже записан во временный каталог
ИмяФайла = КаталогВременныхФайлов() + "document.pdf";
ДвоичныйФайл.Записать(ИмяФайла);
ФайловыйПоток = Новый ФайловыйПоток(ИмяФайла, РежимОткрытияФайла.Открыть);
ЗапросHTTP = Новый HTTPЗапрос(АдресСтраницы);
ЗапросHTTP.Заголовки.Вставить("Content-Type", "application/pdf");
ЗапросHTTP.Заголовки.Вставить("Authorization", "Bearer " + МойТокен);
// Устанавливаем тело напрямую из потока
ЗапросHTTP.УстановитьТелоИзПотока(ФайловыйПоток);
ОтветHTTP = Соединение.ОтправитьДляОбработки(ЗапросHTTP);
ФайловыйПоток.Закрыть(); // Не забываем закрывать потоки
Большинство современных веб-сервисов (написанных на 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.УстановитьТелоИзДвоичныхДанных(ТелоЗапроса.ЗакрытьИПолучитьДвоичныеДанные());
Выясним еще несколько критических моментов, которые помогут избежать ошибок в промышленной эксплуатации:
Новый ЗащищенноеСоединениеOpenSSL() без параметров 1С полагается на настройки ОС. Если сервер требует специфический протокол (например, только TLS 1.2), может потребоваться уточнение параметров в конструкторе.ПолучитьИмяВременногоФайла(), всегда оборачивайте код в блок Попытка...КонецПопытки, чтобы гарантированно удалить файл в блоке Финально (или после отправки), предотвращая засорение диска сервера 1С.HTTPСоединение (например, 60 или 120 секунд), чтобы избежать разрыва связи по инициативе клиента.Подводя итог, отметим, что выбор метода (Base64, бинарный поток или multipart) зависит исключительно от спецификации API принимающей стороны. Однако наиболее грамотным и универсальным с точки зрения производительности 1С является использование потоков и бинарной передачи данных без промежуточного кодирования в строку. Для практического освоения различных сценариев работы с HTTP и передачи файлов подойдёт интерактивный курс по работе с HTTP-запросами в 1С.