HTML в PDF

    html to pdf

    В далеком 2008 году уже была написана подобная статья и я попытался применить знания, но, к сожалению, не справился с русским языком (на denwer-е работал, на хостинге нет). Возможно сказалось отсутствие опыта. А недавно нашел хорошую библиотеку и решил поделиться. Топик, скорее всего, адресован начинающим программистом и ни на, что не претендует.

    Для начала поставим задачу:


    1. Процесс конвертации должен быть простым — минимум кода;
    2. Отображать русский язык «из коробки»;
    3. Понимать html теги, изображения, CSS;
    4. Использовать бесплатную и хорошо документированную библиотеку.

    Вводные данные


    Сам процесс на столько прост, что принципиальной разницы в каком фреймворке его использовать нет. Конвертировать данные из HTML в PDF будем с помощью mPDF.

    Реализация


    Скачиваем и распаковываем в корневую директорию последнюю версию mPDF. Там же создадим файл index.php и добавим следующий код:
    <?php
    $html = '<table_ border="1"><tr_><td_>Пример 1</td_><td_>Пример 2</td_><td_>Пример 3</td_><td_>Пример 4</td_></tr_>
    <tr_><td_>Пример 5</td_><td_>Пример 6</td_><td_>Пример 7</td_><td_><a_ href="http://mpdf.bpm1.com/" title="mPDF">mPDF</a_></td_></tr_></table_>';

    include("mpdf50/mpdf.php");

    $mpdf = new mPDF('utf-8', 'A4', '8', '', 10, 10, 7, 7, 10, 10); /*задаем формат, отступы и.т.д.*/
    $mpdf->charset_in = 'cp1251'; /*не забываем про русский*/

    $stylesheet = file_get_contents('style.css'); /*подключаем css*/
    $mpdf->WriteHTML($stylesheet, 1);

    $mpdf->list_indent_first_level = 0;
    $mpdf->WriteHTML($html, 2); /*формируем pdf*/
    $mpdf->Output('mpdf.pdf', 'I');
    ?>


    Код css-файла:
    table {text-align: center;font-size: 20pt;width: 100%;}

    Работу библиотеки можно проверить на официальном сайте. Или, к примеру, сформировать вышеописанный пример.

    Вот и все. Спасибо.

    P.S.: Огромное спасибо хаброюзерам: rachiu, Zorkus, FeNUMe, Atrax, AusTiN за поддержку и человеческое отношение к новичкам.
    Метки:
    Поделиться публикацией
    Комментарии 81
    • +6
      А в каком, интересно, движке рендерится html?
      • 0
        Извините немного не понял вопрос, не могли бы уточнить.
        • +3
          Ну например разные браузеры рендерят по-разному, и то что выглядит хорошо например(!) в chrome, может не очень хорошо выглядеть в например(!) firefox, и те же css приставки вида -webkit, -moz и прочие.
          • –3
            А, весь же процесс происходит на сервере, так, что от браузера не зависит. Конечно, немного придется поднастроить, что бы все было красиво.
            • +3
              Ну на сервере тоже можно обработать браузерным движком, и, наверняка так и происходит, что-то же его рисует и ставит по местам.
              • –5
                Браузерные движки, видимо, не используются. См., что поддерживается (внизу демки с перечнем того, что поддерживается).
                • +3
                  Странно.
                  Хорошо, уточню: распространённые браузерные движки — gecko/webkit/KHTML/Hv3 и др. — в данном случае не используются, по данной мною ссылке документы, демонстрирующие, что именно поддерживается упомянутым скриптом mPDF.

                  С тем, что на сервере можно использовать gecko или webkit, я, разумеется, не спорю, речь именно об упомянутом скрипте.
        • +1
          по-моему там общераспространенные движки не при делах.
          • НЛО прилетело и опубликовало эту надпись здесь
            • +1
              Вот верный подход :) Даже по примерам PDFов на сайте видно что рендерер у них свой, на пхп. В код смотреть страшно :))
            • +3
              Как я понимаю себе этот механизм, html-страница разбирается либо XML-парсером вроде SimpleXML, либо вообще регулярными выражениями. Строится некоторое дерево команд в памяти. После чего эти команды передаются на некоторый класс Builder, который и строит в соответствии с ними по кирпичикам этот PDF.

              PDF состоит из списков команд, по которым ридер и рисует сам документ

              пример
              %PDF-1.4
              %РФЕШ
              5 0 obj
              >
              endobj
              8 0 obj
              (\376\377\004\043\004\101\004\102\004\060\004\075\004\076\004\062\004\072\004\060\000\040\000F\000r\000e\000e\000B\000S\000D\000\040)
              endobj
              9 0 obj
              >
              endobj
              12 0 obj
              (\376\377\004\022\004\113\004\061\004\076\004\100\000\040\004\117\004\067\004\113\004\072\004\060)
              endobj
              13 0 obj
              >
              endobj

              От версии к версии формат этих команд менялся…
            • +2
              Спасиба :) в свое время угрохал много сил и времени на экспорт отчетности в PDF.
              Библиотека действительно хороша.
              • 0
                А как у него с фоновыми изображениями в элементах и возможность задания фона для каждого листа? Например, фирстиль.
                • +1
                  Вы знаете, я честно говоря не пробовал :) — использовал в основном для бухгалтерских отчетов. Надо тестировать, скачайте дистрибутив, там очень много примеров.
                  • 0
                    угу, я уже прочитал, поддерживает только bg-color. Я пользовался его прародителем HTML2FPDF и это его больное место — нет бекграундов и не может(не мог) генерировать input[type=text], плохо с абсолютным позиционированием и иногда с float нестабилен был. но 2 года назад это все равно лучшее, что вообще удалось найти php-based.
                    • 0
                      Подтверждаю. Сам довольно продолжительное время пользовался этой библиотекой.
                      Сейчас, судя по всему, проект окончательно заглох, а жаль.
                      • 0
                        @page background-image in the form url(image.png) or url('image.png') supported.
                        Может Вы не так прочитали?
                  • +4
                    $mpdf->charset_in = 'cp1251';

                    А можно в UTF-8?
                    • 0
                      вот ответ на Ваш вопрос =)

                      A PHP class to generate PDF files from HTML with Unicode/UTF-8 and CJK support
                      • 0
                        Да, можно.
                      • +2
                        office.webproduction.com.ua:3000/projects/packages/repository/show/trunk/PDF
                        svn://svn.webproduction.com.ua/packages/trunk/PDF/ (read-only free)

                        UTF-8, понимает таблицы, вложенные таблицы, div-ы, почти весь css, img, img на фоне и т.д.
                        Пробовали формировать PDFку на 100+ страниц — только нужно памяти много (очень много).
                        • +12
                          На мой вкус, очень хорошее средство wkhtmltopdf. Рендерит как Webkit, вызывать можно из командной строки чем и как угодно.
                          • 0
                            Интересно как он картинки обрабатывает: для экрана достаточно 72/90dpi, а на печать от 300dpi. Собственно, можно ли там использовать картинки с высоким dpi или он все равно при отрисовки и сохранении в файл проставит 72dpi?
                            • 0
                              По моему опыту использования, он генерирует очень лёгкие pdf-ки и качество картинок неважное. Но, у него куча разных параметров, и один из них — "--disable-pdf-compression" — вроде бы, положительно влияет на качество.

                              Просто, у меня такой задачи не стояло. Предлагаю Вам попробовать самим.
                            • 0
                              Хорошая штука, жалко только что оно за собой весь xorg тащит.
                              • 0
                                вроде как статическая сборка с патченным qt не тащит
                                • 0
                                  Видимо, не тащит. Но этот lzma у меня не распаковывается, пишет «SetDecoderProperties() error»
                            • +1
                              Да, mPDF — одна из лучших бесплатных библиотек для создания pdf-файлов.
                              Тестировал 5 подобных библиотек, из всех них mPDF оказалась самой функциональной, которая умеет преобразовывать html в pdf и при этом дружит с русским языком.
                              • 0
                                Да, тоже перепробовал очень много, остановился на этой.
                                • +1
                                  вот вы бы поделились бы нормальным обзором. с плюсами и иминусами
                                  • +1
                                    >>вот вы бы поделились бы нормальным обзором.
                                    ну может быть, когда-нибудь, как выйду из минусов :))))
                                  • 0
                                    tcpdf — тоже одна из лучших и развивающихся. и функционал не меньше. правда для русского прийдется немного повозится со шрифтами.
                                    • +1
                                      >>правда для русского прийдется немного повозится со шрифтами.

                                      Вот именно, придется повозиться со шрифтами :)
                                      Насколько я помню, для tcpdf их нужно было генерировать, т.е. еще дополнительно нужно было ставить библиотечки…

                                      Для генерации инвойсов и прочих счетов с поддержкой русского языка из HTML-формата, mPDF — достаточно с головой. Поставил и «поехал», на лишние заморочки времени нет.
                                  • +1
                                    Спасибо за топик. Добавлю эту возможность в свой текущий проект, очень в тему:)
                                    • –15
                                      О, думаю тут собрались все pdf-мастера, внимание вопрос:
                                      Когда у меня была чистенькая винда, я с дуру поставил FoxitReader и все браузеры стали ассоциировать открываемые pdf файлы именно с фокситом. Потом я поставил себе Adobe и удалил FoxitReader. После чего у меня при чтении pdf файла через браузер возникает ошибка «FoxitReaderOCX.ocx failed to load». Теперь приходится сохранять все pdf файлы на компьютер и смотреть с компа. О Хабралюди, услышьте меня, помогите мне, что нужно сделать чтобы мой FireFox ассоциировал открываемые pdf файлы с Adobe?
                                      • +1
                                        В накстройках же есть вкладка Applications, в ней и задаюстся программы по умолчанию.
                                        • +1
                                          У меня была такая же проблема.
                                          Но, заходя на очередной варезный сайт и видя надпись «FoxitReaderOCX.ocx failed to load», я только радовался, потому что знал — еще один вирус прошёл мимо меня :)
                                          PDFки, которые мне действительно нужны, я сохранял и смотрел ч.н. offline.
                                        • +2
                                          Недавно потратил прилично времени на поиск толковой либы… С мПхп к сожалению не удалось столкнуться. Вот, та на которой остановился. Выглядит очень мощной. www.html2pdf.fr/en/default
                                          • +2
                                            «mPDF is a PHP class...»

                                            Может стоит перенести топик в блог PHP?
                                            • 0
                                              Прошлая статья была в Web-разработке, вот я и эту сюда добавил.
                                                • +1
                                                  Т.е. вам таки не свойственно учиться на своих ошибках?)
                                                  • 0
                                                    :) не статью ту не я писал, к сожалению, если вы про это.
                                                    • 0
                                                      Oops :) Ну всё равно, подумайте лишний раз о том, чтобы топик в соответствующий блог перенести. Спасибо!
                                              • +1
                                                >А можно в UTF-8?

                                                Можно, mPDF — как раз отлично работает с русским utf, в отличие от остальных
                                                • 0
                                                  А как там русским?
                                                • 0
                                                  В комбинации со встроенной в хром pdf-смотрелкой теперь можно начинать делать сайты целиком на pdf :)
                                                  На самом деле ведь в pdf даже собственный javascript вшит, и «кроссбраузерно», и для форм есть удобнейшие вещи.
                                                  • 0
                                                    BTW: На счет dompdf я когда-то хотел написать статью, о том как нам сервер хакеры взломали… Взломали через dompdf, там дыра!
                                                    • +1
                                                      А у него есть возможность управлять «постраничностью» в html-тэгах? Или вообще как-нибудь?

                                                      А то есть задача: Выводить заголовок + таблица (накладная, счет, например). Вот и нужно, чтобы на каждой новой странице выводился ее номер, шапка, кол-во строк на листе, суммы и т.д.

                                                      Может данная либа с этим справиться? Сейчас у меня с этим справляется TCPFD, но она очень неповоротливая и PDF файлы слишком большие для примитивных отчетов получаются. И то не без шаманства.

                                                      Может кто пробовал? Поделитесь опытом?
                                                      • 0
                                                        А Вы не пробовали использовать pdflatex для этих целей? По-моему самое то, когда речь идет о документах с жесткими требованиями к оформлению. Я с помощью php обычно только шаблон для LateX генерирую, а потом скармливаю его pdflatex. На выходе — красивая pdf-ка с соблюдением всех требований к документации. Единственный минус — нужно разобраться в LaTeX'e, чтобы сделать каркас шаблона.
                                                        • 0
                                                          Да. Это интересная идея для базы, работающей на выделенном сервере. Но может не подойдет для интеграции в интернет-магазин, который размещается на шареде…

                                                          В любом случае спасибо за идею. Попробую.
                                                        • 0
                                                          CSS page-break-*?
                                                        • 0
                                                          Вы не искали альтернативы, чем они лучше-хуже?
                                                          • 0
                                                            Искал, все хорошие, все мощные, но вот с русским языком были проблемы, а тут все хорошо. Англоязычных программистов, видимо, не очень интересует наш великий и могучий.
                                                          • +1
                                                            Я помню, отчаявшись найти нормальные скрипты по сохранению документов в pdf и doc, мы нашли решение следующего плана:
                                                            — на сервере устанавливается OpenOffice & python
                                                            — из php-скрипта запускается команда на питоне, которая вызывает OpenOffice и сохраняет переданный html в выбранный нами формат.
                                                            Из минусов было только то, что конечный вид файла зависел от версии OO.
                                                            • 0
                                                              А как эта либа с большими данными работает? Требует много памяти?
                                                              • 0
                                                                Думаю, что прилично. Я просто на производительность их не тестировал. Использовал для проекта внутренней сети компании — там был отдельный сервер.
                                                                • +1
                                                                  Два дня назад столкнулся с тем, что плагин на базе mPDF работает на сайте везде, кроме той страницы где он нужен, — руководство пользователя FreeNAS в 70+ страниц и больше сотни картинок. Не успевает отрендерить и отваливается по таймауту. Хостинг коллективный на «Инфобокс», таймаут для меня никто менять не будет, и остался я (вернее, читатели) без экспорта в PDF.
                                                                    • +1
                                                                      Можно попробовать, конечно, но думаю это и им в голову приходило. Например, по Ваше ссылке есть примечание о safe mode. А не это так другое придумают.

                                                                      Все это похоже на изготовление самогона в коммунальной кухне с единственной плитой, — начать можно, но долго не протянешь.
                                                                      • +1
                                                                        Надо использовать правильный хостинг ;)

                                                                        На спринтхосте мне удалось из под своего аккаунта даже redis установить (в домашнюю папку) и запустить )))

                                                                        Такие мелочи, как set_time_limit тоже работают.

                                                                        А вообще не думаю, что на хостинге PHP будет запущен в safe mode… Это слишком жестоко…
                                                                        Посмотрите, что пишет php_info()…
                                                                        • 0
                                                                          Спасибо за совет, узнал новое (для меня PHP темный лес). Но вряд ли этим займусь сейчас: все-таки мой сайт это только хобби, да и экспорт в PDF не ключевая фича. У меня там есть экспорт в ODF, — как замена.

                                                                          Насчет хостинга Вы, вероятно, правы. Единственное решение которое мне там предложили — переезд на VPS, с заметной для меня разницей в цене.
                                                                    • 0
                                                                      У меня была похожая проблема — отрендерить таблицу из 5к строк. Хостинг свой, поэтому таймаут я поменял, но по памяти не влезло, ему не хвататет даже 512 метров на процесс!
                                                                      Что-то мне подсказывает, что PDF по-хорошему надо генерить с помощью сторонних утилит, а не средствами PHP.
                                                                      • 0
                                                                        У инфобокса на хостинге можно редактировать php.ini. Там можно задать свой таймаут и memory_limit. напишите в поддержку, они вам дадут доступ на редактирование.
                                                                        • 0
                                                                          Уже. И в тех.поддержку и сюда в их блог. Ответ одинаковый. Менять таймаут они не хотят.
                                                                    • 0
                                                                      нда. ребята прикалываются. (см. русский и украинский)
                                                                    • 0
                                                                      Зачем нужен этот закрытый формат? Как потом отредактировать этот pdf, добавит страницу, перевернуть?
                                                                      • +4
                                                                        Он рожден быть закрытым. ;) Идеей было — заменить бумажные документы. Оттуда и всякие фичи типа запрета на редактирование и «невозможности» копирования. За это его в бизнесе и любят.
                                                                      • 0
                                                                        А кто-нибудь мне может объяснить, зачем вообще нужна server-side генерация pdf из html?
                                                                        Пусть юзеры сами ставят себе виртуальные принтеры и конвертируют что хотят в любых количествах.
                                                                        • 0
                                                                          Например, у нас в компании, это было сделано, для того, что бы пользователь смог ввести данные в форму и сформировать заявку, на предоставление/изменение доступа к какому либо ресурсу и. т. д.

                                                                          А pdf потому, что филиалы находятся по всей стране, пользователей много (ИТ-специалистов мало), да и с принтерами, в удаленных уголках, иногда проблемы (работник может сохранить на флешку и распечатать на другом принтере). И выглядит pdf на всех компьютерах одинаково.
                                                                          • 0
                                                                            Invoices
                                                                          • +1
                                                                            Интересует возможность подписи созданных PDF'ok сертификатами. Никто не пробовал?
                                                                            • 0
                                                                              Было бы здорово. Но, наверно, это из области фантастики…
                                                                              • +1
                                                                                Спасибо. Когда-то искал нормальные библиотеки, не нашёл. Эта работает вполне прилично: news.sfu-kras.ru/pdf/7259
                                                                                • 0
                                                                                  я, конечно, извиняюсь, но кто-нибудь догадался посмотреть исходник? 30 тысяч строк говнокода в одном файле. я такое даже тестировать не буду.
                                                                                  • 0
                                                                                    mPDF полностью убивает ссылки при слиянии нескольких pdf, что грустно.
                                                                                    • 0
                                                                                      Не поддерживает z-index.

                                                                                      Только полноправные пользователи могут оставлять комментарии. Войдите, пожалуйста.