Часто при интеграции 1С с веб-сайтами (например, на базе 1С-Битрикс) возникает задача: получить сформированный печатный документ (счет, акт, накладную) в формате PDF напрямую из HTTP-сервиса 1С и сразу же отобразить его пользователю в браузере. Разберем по шагам, как правильно настроить авторизацию, получить двоичные данные файла и вывести их на экран без промежуточного сохранения на сервере сайта.
Для обращения к HTTP-сервису 1С из PHP чаще всего используется библиотека cURL. Поскольку сервис 1С обычно закрыт паролем, нам необходимо передать данные для авторизации. Рассмотрим рабочий вариант кода, где мы формируем заголовок Authorization: Basic.
Для передачи учетных данных мы кодируем связку логина и пароля в формат Base64 и отправляем в виде HTTP-заголовка. Проанализируем пример кода:
$user = "1";
$password = "1";
$base64 = base64_encode("$user:$password");
$headers = Array();
array_push($headers, 'Content-Type: application/x-www-form-urlencoded');
array_push($headers, 'Authorization: Basic ' . $base64);
$curl = curl_init();
$uri = "http://domen.online/UT1/hs/CreatePDF/";
curl_setopt($curl, CURLOPT_RETURNTRANSFER, true);
curl_setopt($curl, CURLOPT_URL, $uri);
curl_setopt($curl, CURLOPT_CUSTOMREQUEST, 'GET');
curl_setopt($curl, CURLOPT_HTTPHEADER, $headers);
curl_setopt($curl, CURLOPT_HEADER, false);
$response = curl_exec($curl);
В этом примере мы указываем параметр CURLOPT_RETURNTRANSFER как true. Это крайне важно, так как мы хотим получить двоичные данные PDF-файла в переменную $response, а не выводить их сразу в стандартный поток (что привело бы к ошибке отображения).
Альтернативный способ авторизации: cURL имеет встроенную опцию CURLOPT_USERPWD, которая выполняет ту же работу под капотом. Если вы используете её, следите за тем, чтобы не брать переменную с URL в одинарные кавычки, иначе cURL попытается перейти по строке "$url", а не по фактическому адресу.
Итак, в переменной $response у нас теперь хранятся двоичные данные PDF. Если мы просто выведем эту переменную через echo, браузер покажет "кракозябры" (исходный код PDF, начинающийся с %PDF-1.7 и прочих служебных символов). Чтобы браузер понял, что это PDF-документ, и открыл его в своем встроенном просмотрщике, нам необходимо передать правильные HTTP-заголовки.
Рассмотрим код, который необходимо выполнить сразу после получения ответа от 1С:
$filename = "bill.pdf";
// Указываем тип контента
header('Content-type: application/pdf');
// Указываем, что файл нужно открыть в браузере (inline), а не скачивать (attachment)
header('Content-Disposition: inline; filename="' . $filename . '"');
header('Content-Transfer-Encoding: binary');
header('Content-Length: ' . strlen($response));
header('Accept-Ranges: bytes');
// Выводим содержимое файла
echo $response;
Ключевой заголовок здесь — Content-Disposition: inline. Именно он заставляет браузер открыть файл на всю страницу. Если бы мы хотели принудительно заставить пользователя скачать файл на жесткий диск, мы бы использовали значение attachment.
Даже если вы правильно написали код из первых двух шагов, при работе в системе 1С-Битрикс вы можете столкнуться с тем, что вместо красивого документа выводится текст с бинарным мусором. Проанализируем причину этой популярной ошибки.
Проблема кроется в попадании сторонних символов в буфер вывода до того, как отправляются заголовки header(). Это может быть:
<?php< в вашем скрипте стоит хотя бы один пробел, он отправляется в браузер. Сервер при этом автоматически отправляет заголовок Content-Type: text/html, и наши заголовки PDF игнорируются или ломаются.require($_SERVER["DOCUMENT_ROOT"]."/bitrix/header.php");, Битрикс начинает выводить шапку сайта (HTML-каркас). Двоичные данные PDF смешиваются с HTML, что полностью разрушает структуру документа.Как правильно отдавать файлы в Битрикс:
Во-первых, для служебных скриптов (отдача файлов, обработчики AJAX-запросов) необходимо использовать только служебный пролог, который инициализирует ядро системы, но не выводит визуальную часть:
require($_SERVER["DOCUMENT_ROOT"]."/bitrix/modules/main/include/prolog_before.php");
Во-вторых, хорошей и надежной практикой является принудительная очистка буфера вывода перед отправкой файла. Для этого перед блоком с header(...) вызовем функцию очистки:
// Очищаем весь случайный вывод (пробелы, переносы строк, возможные нотисы)
while (ob_get_level()) {
ob_end_clean();
}
// Теперь можно смело отправлять заголовки
header('Content-type: application/pdf');
// ... остальные заголовки
echo $response;
exit; // Обязательно прерываем скрипт, чтобы дальше ничего не вывелось
Используя этот подход, мы гарантируем, что браузер получит чистый поток байтов PDF-файла без примеси HTML-тегов или невидимых пробелов. Это позволит открыть печатную форму напрямую из 1С в интерфейсе сайта плавно и без создания временных файлов на диске веб-сервера.