Генерация HTML в PDF через wkhtmltopdf

PHP
image
К написанию данной статьи меня сподвиг следующий пост.
Пришлось мне как-то столкнуться с задачей генерирования pdf файла из имеющейся страницы сайта. Заказчик хотел, что бы у посетителя была возможность получить в pdf текущую страницу его интернет-магазина. Причем получить именно в том виде, который лицезреет клиент, только без заголовка и шапки сайта. Пример буду описывать для сайта на системе управления Битрикс, поскольку именно на нем был сайт, для которого создавался функционал.
Порывшись по интернету и поискав различные библиотеки генерации pdf на базе php понял, что дело дрянь. Все варианты, что я пробовал, имели существенные ограничения по поддержке CSS. Упомяну, что хотелось сделать «кроссерверно», то есть, что бы, при переносе сайта на другой хостинг, функциональность сайта не пострадала. Как выяснилось впоследствии, этого было не достичь. Поломав голову, решил использовать программные решения. Поскольку сайт крутился на арендованном сервере, у меня был полный доступ к системе. Еще немного порыскав по интернету, нашел практически единственное решение, идеально подошедшее мне и, думаю, которое подойдет многим другим пользователям. Имя этому решению wkhtmltopdf. Это утилитка генерации pdf из html, которая использует возможности WebKit'а, веб-рендера на котором основан, в частности, Apple Safari. Утилитка работает из командной строки, что нам и требуется.

Родная страница проекта.
Последняя доступная версия 0.10.0 beta4.
Работает практически на любой ОС. Я проверял работу на базе CentOS 5.5.
Скрипт требует для работы X11, gcc и openssl. Так же для правильного компилирования требуется наличие Qt. В примечаниях к установке указывается, что Qt желательно ставить путем компиляции, если ставить из дистрибутива, не все опции будут доступны. Я ставил Qt из дистрибутива и использовал готовый бинарник, никаких проблем в работе конвертера замечено не было.
Подробная инструкция по установке здесь.

После установки естественно сразу не заработало так, как надо. Проблема была в том, что русские шрифты отображались квадратиками. Проблема решилась установкой руских шрифтов.

Итак, конвертер установлен. Надо его проверить. Для проверки достаточно из консоли дать команду:

wkhtmltopdf <адрес_сайта> <имя файла>


В текущем каталоге будет создан фаил с указанным именем. Проверяем, смотрим на ошибки, если есть. Ищем способы устранения и устраняем.

Далее нам надо интегрировать утилитку с нашим сайтом. Для этого требуется, что бы были разрешения на выполнение php команды exec.

Итак, разрешения есть, конвертер установлен и протестирован. Начинаем собственно интеграцию в наш сайт. У меня был сайт на системе управления Битрикс. Поскольку нужно выводить только содержимое страницы без шапки, подвала и всех менюшек, был создан скрипт, в котором подключалось только АПИ Битрикса и нужный мне компонент вывода каталога.

Строка подключения АПИ Битрикс без вывода шаблона:

require($_SERVER["DOCUMENT_ROOT"]."/bitrix/modules/main/include/prolog_before.php");


Далее подключаем нужный нам компонент с требуемыми параметрами. Параметры можно передавать методом GET, то есть в строке запроса страницы.

Подготовив страницу вывода контента, готовим скрипт вызова нашего конвертера.
Конвертеру можно напрямую передавать адрес веб страницы из котрой будет генерится пдф. Так же есть множество различных параметров вызова для управления отображением страницы. В частности можно задать отступы от краев, содержание колонитулов и множество других параметров. Получить список всех параметров можно, вызвав конвертер из консоли с параметрами:
--manpage Выводит страницу мануала
--htmldoc Выводит страницу мануала в html формате
--readme Выводит readme

Мне нужно было использовать нижний колонтитул. Содержание колонтитула можно передавать в html виде.
Параметр ответственный за нижний колонтитул --footer-html. Значением этого параметра может быть адрес страницы с html содержимым.
Итого имеем примерно следующий php скрипт, который генерирует pdf фаил и отдает его браузеру на скачивание:

$cd = "cd <путь к каталогу куда положить фаил>";
exec($cd);
$comand = "wkhtmltopdf --footer-html <страница с содержанием нижнего колонтитула> \"http://<адрес_сайта>/catalog/$cat_id/?parametr1=$value1¶meter2=$value2\" catalog.pdf";
exec($comand);
if (file_exists("<путь до файла>/catalog.pdf")) {
 header('Content-type: application/pdf');
 header('Content-Disposition: attachment; filename="catalog.pdf"');
 readfile('<путь до файла>/catalog.pdf');
}
unlink("<путь до файла>/catalog.pdf");


Описание скрипта по порядку:
1) задаем корневой каталог, куда свалится pdf. Делается на всякий случай, что бы потом не думать, почему не отдается фаил.
2) Формируем команду с различными параметрами. Параметры передаются методом GET. Получение параметров не описано, но оно так же сделано методом GET с фильтрацией входящих переменных, дабы не дать нехорошим людям реализовать их злые или не очень намерения.
3) Исполняем сформированную команду.
4) Проверяем, создался ли файлик и, выставив нужные заголовки, отдаем фаил браузеру.
5) Удаляем фаил.

Вот собственно простенький пример как генерировать pdf фаил из html, с полной поддержкой CSS. Да, у WebKit'a есть свои нюансы отображения, но о них известно и их можно легко учесть, чего не сделать, используя библиотеки генерации на базе php. В заметке была описана интеграция в сайт на системе управления Битрикс, точно таким же способом утилитка может использоваться на любом другом сайте, отличия будут заключаться только в скрипте вывода контента.


1 комментарий

avatar
Спасибо за хорошую статью единственную на русском. Хотел спросить почему Ваш сайт так подозрительно похож на хабр?
Только зарегистрированные и авторизованные пользователи могут оставлять комментарии.