Бывают случаи, когда веб-приложение должно создавать PDF файл. Для этой задачи можно использовать html2pdf – набор сценариев для преобразования HTML страницы в PDF с помощью PHP.
Скачиваем и устанавливаем html2pdf
Библиотеку html2pdf можно найти по адресу
Чтобы использовать html2pdf, на сервере должна быть установлена одна из библиотек Ghostscript или PDFLib. PDFLib создает высококачественные и быстро отображающиеся PDF файлы, но это платная библиотека, для которой необходимо приобрести лицензию. Ghostscript генерирует приемлемые результаты для большинства целей. При использовании Ghostscript сначала HTML преобразуется в Postscript, а затем в PDF. В результате сценарий потребляет довольно много ресурсов.
Убедитесь что php.ini позволяет устанавливать ограничение памяти для PHP 32-64MB. Также установите максимальное время выполнения сценария 2-3 минуты. По умолчанию это значение составляет 30 секунд. Мой проект изначально работал нормально с такой настройкой, но как только понадобилось генерировать больше PDF-файлов, стали часто происходить тайм-ауты.
Другие требования включают в себя PHP 4.1 или выше. html2pdf будет прекрасно работать с PHP 5. На самом деле, мой проект был проверен на PHP 5.3, и работал прекрасно. В PHP должны быть подключены расширения GD и DOM XML. Также настоятельно рекомендуется установить расширение Zlib.
Настройка html2pdf
К счастью, html2pdf почти не нужно настраивать для использования. Все настройки, которые необходимо изменить, расположены в файле config.inc.php.
Наиболее актуальными элементами является путь к исполняемому файлу Ghostscript (на большинстве дистрибутивов Linux это /usr/bin/gs) и путь к вашему хранилищу Type 1 шрифтов (опять же на большинстве Linux-систем: /usr/share/fonts/type1/gsfonts). Если вы используете PDFLib, наиболее важные элементы конфигурации включают в себя расположение библиотеки, лицензионного ключа и файла конфигурации PDFLib.
К дополнительным параметрам конфигурации относится имя файла по умолчанию для создаваемых PDF-файлов. Вы также можете установить кодировку по умолчанию и строку User-Agent, которую передает класс-получатель(fetcher) html2pdf, когда запрашивает HTML для преобразования.
Создание PDF
html2pdf обработает все связанные стилевые таблицы и воспроизведет HTML, чтобы создать PDF. В результате библиотека извлекает страницу, которую нужно конвертировать, с помощью класса-получателя. Хотя вы можете написать собственные классы-получатели для обработки различных ситуаций, например, для работы с аутентификацией, мы рассмотрим простой метод загрузки HTML страницы и создания из неё PDF файла.
Первым шагом является включение необходимых файлов из html2pdf. Далее приведен код для включения необходимых файлов (если вы установили html2pdf в подкаталог /html2pdf):
1 2 3 4 |
<?php require_once('html2pdf/config.inc.php'); require_once('html2pdf/pipeline.factory.class.php'); ?> |
Следующим шагом является разбор файла конфигурации для html2ps, который преобразует HTML к временному файлу Postscript, чтобы Ghostscript мог конвертировать его в PDF. Это делается с помощью следующей команды:
1 2 3 |
<?php parse_config_file('html2pdf/html2ps.config'); ?> |
Для html2pdf требуется несколько глобальных переменных для хранения конфигурационной информации. Первой переменной является массив, который содержит набор параметров концигурации, управляющих воспроизведением HTML. Так выглядит мой код:
1 2 3 4 5 6 7 8 9 10 11 12 |
<?php global $g_config; $g_config = array( 'cssmedia' => 'screen', 'renderimages' => true, 'renderforms' => false, 'renderlinks' => true, 'mode' => 'html', 'debugbox' => false, 'draw_page_border' => false ); ?> |
Некоторые из этих параметров заслуживают дополнительного обсуждения. Можно указать html2pdf, какие CSS файлы использовать, настроив параметр cssmedia. Если вы определили специальные файлы CSS для печати, установка значения cssmedia в "print" приведет к тому, что эти файлы будут использоваться вместо таблиц стилей "screen". Для моего проекта я хотел сохранить то же форматирование, как при просмотре HTML, поэтому я установил значение cssmedia равным "screen".
Если у вас возникли некоторые проблемы с выводом PDF, можно установить параметр debugbox в true. Данный параметр обводит каждый блок при выводе PDF. Это позволяет выполнять отладку генерирования PDF и видеть, как элементы HTML блока преобразуются в PDF.
Может показаться, что renderfields делает что-либо с полями формы, но это не так. Настройка renderfields влияет на то, как специальные поля, такие как ##PAGE##, обрабатываются в html2pdf.
Настройка renderfields работает с интерактивными PDF формами. Также renderfields определяет, воспроизводятся ли в PDF внутренние и внешние ссылки.
Следующий шаг в подготовке к созданию PDF заключается в настройке размера носителя и полей. Опять же далее приведен мой код:
1 2 3 4 5 6 7 8 9 10 11 |
<?php $media = Media::predefined('Letter'); $media->set_landscape(false); $media->set_margins(array( 'left' => 15, 'right' => 15, 'top' => 25, 'bottom' => 0 )); $media->set_pixels(960); ?> |
Я использую предопределенный размер носителя, "Letter" в данном случае. В библиотеке содержится группа предопределенных носителей таких, как "Letter", "A4" и т.д. Следующий параметр определяет, использовать ли альбомную ориентацию. В моём проекте была нужна портретная ориентация, поэтому этот параметр установлен в false. Поля страницы установлены с помощью массива. В нем числовые значения установлены в миллиметрах. Для моего проекта, я оставил нижнее поле равным 0, поскольку я определил разрывы страниц, то установка нижнего поля вызвала бы прерывание вывода в непредсказуемом месте. Наконец, нужно указать html2pdf, как масштабировать вывод. Это делается с помощью установки максимальной ширины HTML страницы в пикселях. Это значение будет использовано для вычисления размера PDF. Поскольку я использую Blueprint CSS framework, страница ограничивается 960 пикселями.
Далее определим коэффициенты масштабирования:
1 2 3 4 5 6 7 |
<?php global $g_px_scale; $g_px_scale = mm2pt($media->width() - $media->margins['left'] - $media>margins['right'] ) / $media->pixels; global $g_pt_scale; $g_pt_scale = $g_px_scale * 1.43; ?> |
Сначала вычисляем масштаб в пикселях. Для этого берём ширину носителя и вычитаем размер правого и левого полей. После делим её на ширину HTML в пикселях. Затем это число умножается на 1.43 для получения нужного масштаба.
Класс-конвейер выполнит все преобразования:
1 2 3 4 5 6 |
<?php $pipeline = PipelineFactory::create_default_pipeline("", ""); $pipeline->pre_tree_filters[] = new PreTreeFilterHTML2PSFields(); $pipeline->destination = new DestinationDownload($filename); $pipeline->process($url, $media); ?> |
Первые две строки это стандартный код, взятый из документации html2pdf. Код создает новый экземпляр класса-конвейера и указывает, как фильтровать HTML для преобразования. Следующие строки нас также интересуют. Третья строка не обязательна. В ней даются указания отправлять файл в виде HTML приложения, чтобы браузер предлагал пользователю скачать файл. В качестве параметра передается имя файла, которое должен иметь скачиваемый PDF. Без этой строки файл будет иметь имя по умолчанию, указанное в config.inc.php ("unnamed" по умолчанию). В следующей строке генерируется PDF файл. В метод process передается два параметра – URL, который нужно конвертировать, и определенный ранее объект $media, который контролирует размер страницы, поля и масштаб.
Разрыв страницы можно вставить с помощью HTML комментария на конвертируемой странице.
С помощью данного кода сценарий html2pdf добавит разрыв страницы. Также существует группа специальных полей, которые будут добавлены к HTML и воспроизведены в окончательном PDF файле, если вы укажете renderfields = true. Эти поля включают в себя текущий номер страницы, общее число страниц, временную отметку. Для получения дополнительной информации по специальным полям смотрите документацию html2pdf .
Создание динамических PDF файлов является распространенной задачей в разработке веб-приложений. Если необходимо создать HTML и PDF версии одной и той же страницы, html2pdf значительно упростит задачу, используя существующую HTML страницу. Основы использования довольно просты, но библиотека является расширяемой, так что вы можете создавать собственные классы, например, для обработки аутентификации. Вы будете удивлены, насколько просто создавать PDF.