Конвертируем HTML в PDF при помощи Dompdf

от автора


PDF — формат, ставший уже стандартом. Он был изначально создан Adobe для представления текста и изображений в документе с фиксированной структурой. Давно не редкость для веб-приложений, поддерживающих скачку данных, таких как счета или отчеты, отдавать их в PDF формате. Так что в этой статье мы пройдем простую генерацию PDF документов используя PHP.

Dompdf — это отличная библиотека, способная генерировать PDF из HTML-разметки и CSS-стилей (в большинстве случаев это стили, совместимые с CSS 2.1 с поддержкой некоторых свойств CSS3). Мы можем определить, как наше содержимое должно выглядеть, используя эти знакомые технологии, и после легко конвертировать его в фиксированный документ. Также эта библиотека имеет и другие полезные и интересные функции.

Приступаем к работе

Dompdf доступен на GitHub и может быть установлен используя Composer. Установка через Composer без каких-либо ошибок часто вызывает трудности, поэтому я рекомендую просто использовать Git для установки Dompdf.

Библиотека требует PHP >= 5.0 с активированными расширениями mbstring и DOM. Также она требует несколько шрифтов, которые обычно доступны на большинстве компьютеров.

Перейдите в директорию, куда собираетесь установить библиотеку и выполните в командной строке:

git clone https://github.com/dompdf/dompdf.git git submodule init git submodule update 

Как только мы скачали Dompdf, давайте напишем короткий пример, который сгенерирует простой PDF документ:

<?php set_include_path(get_include_path() . PATH_SEPARATOR . "/path/to/dompdf");  require_once "dompdf_config.inc.php";  $dompdf = new DOMPDF();  $html = <<<'ENDHTML' <html>  <body>   <h1>Hello Dompdf</h1>  </body> </html> ENDHTML;  $dompdf->load_html($html); $dompdf->render();  $dompdf->stream("hello.pdf"); 

Для того, чтобы использовать библиотеку в проекте, мы сначала подтягиваем файл dompdf_config.inc.php, который содержит большую часть конфигурации Dompdf. Он также загружает autoloader и пользовательский файл конфигурации в котором мы можем переопределить параметры по умолчанию.

HTML-разметка передается как строка в метод load_html(). Альтернативно мы можем загрузить разметку из файла или URL, используя метод load_html_file(). Он принимает имя файла или URL веб-страницы в качестве аргумента.

Метод render() отображает HTML в PDF, и мы готовы к отдаче файла. Метод stream() отправляет результирующий PDF как вложение в браузер. Этот метод имеет необязательный второй параметр, массив опций:

  • Accept-Rangesboolean, отсылает заголовок “Accept-Ranges” (по умолчанию false).
  • Attachmentboolean, отсылает заголовок “Content-Disposition: attachment” заставляя браузер отображать запрос на сохранение (по умолчанию true).
  • compressboolean, включает сжатие содержимого (по умолчанию true).

Только что мы сгенерировали очень простой PDF, но это не совсем практично. В реальности мы часто имеем требования к размеру листа, ориентации страницы, кодировке символов и т.д. Есть целый набор опций, которые мы можем установить, чтобы сделать Dompdf более подходящим для наших реальных потребностей. Все они перечислены и объяснены в файле dompdf_config.inc.php, который устанавливает им значения по умолчанию. Вы можете менять эти значения, обновляя файл пользовательской конфигурации dompdf_config.custom.inc.php. Вот некоторые из важных настроек:

  • DOMPDF_DEFAULT_PAPER_SIZE – устанавливает размер листа по умолчанию для PDF-документа. Поддерживаемые размеры листов вы можете найти в файле include/cpdf_adapter.cls.php (значение по умолчанию — “letter”).
  • DOMPDF_TEMP_DIR – указывает временную папку, используемую Dompdf. Убедитесь, что эта директория доступна на запись согласно настройкам вашего веб-сервера.
  • DOMPDF_UNICODE_ENABLED – устанавливает, будет ли PDF использовать шрифты Unicode (по-умолчанию true).
  • DOMPDF_ENABLE_REMOTE – активирует включение изображений или CSS-стилей из удалённых сайтов (по-умолчанию false).
  • DEBUG_LAYOUT – устанавливает, будет ли отображена граница вокруг каждого HTML блока в PDF файле. Очень удобно для отладки макета (по умолчанию false).

Продвинутое использование

Теперь давайте немного поговорим о продвинутом использовании Dompdf. Возможно мы хотим сохранить сгенерированный PDF документ на диск, вместо того чтобы отсылать его в браузер. Вот как это делается:

<?php $dompdf = new DOMPDF(); $dompdf->load_html($html); $dompdf->render();  $output = $dompdf->output(); file_put_contents("/path/to/file.pdf", $output); 

Вместо вызова stream(), как в прошлом примере, мы используем output(), который возвращает PDF как строку. Этот метод также принимает массив опций, но доступна лишь одна — compress (по умолчанию true).

Dompdf также позволяет нам добавлять хедер и футер к сгенерированному PDF, встраивая PHP-скрипт прямо в HTML, который он отображает. Но из-за того, что обработка произвольного кода может представлять из себя угрозу безопасности, значение конфигурации, которое отвечает за эту функциональность, по умолчанию выключено. Нам необходимо для начала установить опцию DOMPDF_ENABLE_PHP как true.

Как только мы включили выполнение встроенного PHP, объект PDF станет доступным внутри скрипта и мы сможем использовать его для манипуляций со страницей. Мы можем добавлять текст, линии, изображения, прямоугольники и т.д.

$html = <<<'ENDHTML' <html>  <body>   <script type="text/php"> if (isset($pdf)) {     // open the PDF object - all drawing commands will     // now go to the object instead of the current page     $footer = $pdf->open_object();      // get height and width of page     $w = $pdf->get_width();     $h = $pdf->get_height();      // get font     $font = Font_Metrics::get_font("helvetica", "normal");     $txtHeight = Font_Metrics::get_font_height($font, 8);      // draw a line along the bottom     $y = $h - 2 * $txtHeight - 24;     $color = array(0, 0, 0);     $pdf->line(16, $y, $w - 16, $y, $color, 1);          // set page number on the left side     $pdf->page_text(16, $y, "Page: {PAGE_NUM} of {PAGE_COUNT}", $font, 8, $color);     // set additional text     $text = "Dompdf is awesome";     $width = Font_Metrics::get_text_width($text, $font, 8);     $pdf->text($w - $width - 16, $y, $text, $font, 8);      // close the object (stop capture)     $pdf->close_object();      // add the object to every page (can also specify     // "odd" or "even")     $pdf->add_object($footer, "all"); }   </script>   <h1>Hello Dompdf</h1>  </body> </html> ENDHTML; 

Скрипт встроен прямо в HTML-разметку и сначала открывает объект, чтобы мы могли влиять на отображение. Вся отрисовка будет записана в этот объект и мы сможем добавить его на все выделенные страницы (хотя есть и ограничения).

Затем мы получаем реальную ширину и высоту страницы, чтобы посчитать координаты футера, который мы собираемся добавить. Также нам требуется предоставить обьект шрифта, поскольку мы добавляем текстовое содержимое. Font_Metrics::get_font() позволяет создать объект, который нам необходим. Мы также берем высоту данного шрифта из его размера используя get_font_height(), чтобы посчитать позиционирование содержимого футера. Метод get_font_width() возвращает ширину нашего текста для данного шрифта и размера, которую мы также используем в наших вычислениях.

Метод line() рисует линию из точки (X1,Y1) в точку (X2,Y2). Обратите внимание, значение цвета подставляется не совсем в RGB. Основной PDF-класс требует значения между 0 и 1, так что мы конвертируем значения RGB в эти новые значения. Чтобы получить лучшее приближение (approximation), вы можете поделить их на 255.

Мы добавляем номер для каждой страницы, используя метод page_text(), которой принимает координаты X и Y, а также текст, который будет добавлен, объект шрифта, размер шрифта и цвет. Dompdf автоматически заменяет значения для {PAGE_NUM} и {PAGE_COUNT} на каждой странице, и делает $pdf доступным для нас.

Также мы можем не использовать встроенный PHP и достигать аналогичного эффекта прямо из PHP, примерно так:

<?php $dompdf = new DOMPDF(); $dompdf->set_paper("A4");  // load the html content $dompdf->load_html($html); $dompdf->render(); $canvas = $dompdf->get_canvas(); $font = Font_Metrics::get_font("helvetica", "bold"); $canvas->page_text(16, 800, "Page: {PAGE_NUM} of {PAGE_COUNT}", $font, 8, array(0,0,0)); $dompdf->stream("sample.pdf",array("Attachment"=>0)); 

Обратите внимание, мы размещаем код после вызова $dompdf->render() потому что мы, по существу, редактируем уже созданный PDF.

Подведем итоги

В этой статье мы обсудили простой способ конвертировать HTML в PDF используя Dompdf. Несмотря на то, что Dompdf отличная библиотека, она не является полностью универсальным решением для генерации PDF документов; она все же имеет определенные ограничения и проблемы. Dompdf не очень терпимо относится к плохо оформленному HTML и большие таблицы могут легко привести к переполнению памяти. Некоторые базовые функции CSS, такие как float не полностью поддерживаются. И вообще, поддержка CSS3 очень ограничена. Если вам необходимы функции, которые не поддерживаются в Dompdf, вам может помочь к примеру wkhtmltopdf. Тем не менее, Dompdf является очень простым и удобным инструментом для решения большинства задач по экспорту PDF.

На самом деле довольно трудно объяснить все функции библиотеки в статье вроде этой, поэтому не забудьте просмотреть документацию и исходный код, а также изучите такие полезные функции, как добавление колбэков, использование своих шрифтов и др.

ссылка на оригинал статьи http://habrahabr.ru/post/190364/


Комментарии

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *