HTML2PDF в PHP - конвертировать утилиты и скрипты - примеры и демонстрации - PullRequest
5 голосов
/ 28 марта 2012

У меня довольно сложный макет HTML / CSS, который я хотел бы преобразовать в PDF на моем сервере. Я уже попробовал DOMPDF, к сожалению, он не конвертировал HTML с правильным макетом. Я рассмотрел HTMLDOC, но я слышал, что он в значительной степени игнорирует CSS, поэтому я полагаю, что компоновка этого инструмента тоже развалится.

У меня такой вопрос: есть ли онлайн-демонстрации для других инструментов (например, wkhtmltopdf, т.е.), которые я мог бы использовать, чтобы проверить, как конвертируется мой HTML? Прежде чем провести остаток своей жизни, устанавливая и тестируя один за другим?

К сожалению, я не могу изменить макет HTML, чтобы соответствовать этим инструментам. Или лучше сказать - я мог бы, если бы любой из них приблизился бы к приемлемому результату ...

1 Ответ

11 голосов
/ 29 марта 2012

Не совсем ответ, но на вопрос выше, но я постараюсь рассказать о своем опыте, может быть, он поможет кому-нибудь где-нибудь в будущем.

  1. wkthmltopdf - это действительно ЕДИНСТВЕННОЕ решение , которое сработало для меня и может дать то, что я называю приемлемыми результатами.Тем не менее, некоторые незначительные изменения в CSS должны были быть сделаны, однако, он работал очень хорошо, когда дело доходит до рендеринга контента.Все остальные пакеты действительно подходят только в том случае, если у вас достаточно простой документ с одной базовой таблицей и т. Д. Нет возможности получить их для получения достоверных результатов по сложным документам с элементами дизайна, CSS, несколькими перекрывающимися изображениями и т. Д. Если в игре используются сложные документы- не тратьте время (как я) - иди прямо к wkhtmltopdf .

  2. Осторожно - установка wkhtmltopdf сложна .Мне было не так легко, как ребята сказали в своих комментариях (одна из причин может заключаться в том, что я не слишком знаком с Linux).Статический двоичный файл не работал для меня по какой-то причине, которую я не могу объяснить.Я подозреваю, что были проблемы с версией - очевидно, есть разница между версиями для разных ОС и процессоров, возможно, у меня версия vrong.Для установки нестатической версии, прежде всего, вам нужен root-доступ к серверу, это очевидно. Я установил его с apt-get, используя PuTTy , прошло довольно хорошо.Мне повезло, что мой сервер уже имел все предрасположенности для установки wkhtmltopdf.Так что это было легко для меня :) (кстати, вам не нужно заботиться о символических ссылках или обёртках, как говорят многие уроки - я потратил часы, пытаясь понять, как выполнить эту часть, в конце концов, я дал ееи все работает хорошо, хотя)

  3. После установки я получил довольно известную ошибку Cannot connect to X server.Это связано с тем, что нам нужно запустить wkhtmltopdf без заголовка на «виртуальном» x сервере .Обойти это было также довольно просто (если не заботиться о символических ссылках). Я установил его с apt-get install xvfb.Это также прошло довольно хорошо для меня, никаких проблем.

  4. После завершения я смог запустить wkhtmltopdf.Осторожно - мне потребовалось некоторое время, чтобы понять, что попытка запустить xvfb была неправильным путем - вместо вы должны запустить xvfb-run.Мой PHP-код теперь выглядит следующим образом exec("xvfb-run wkhtmltopdf --margin-left 16 /data/web/domain.com/source.html /data/web/domain.com/target.pdf"); (обратите внимание на параметр командной строки --margin-left 16 для wkhtmltopdf - он делает мой контент более центрированным; я оставил его на месте, чтобы продемонстрировать, как можно использовать параметры командной строки).

  5. Я также хотел защитить сгенерированные файлы PDF от редактирования (в моем случае, защита печати также возможна).После некоторого исследования я обнаружил этот класс из ID Security Suite .Прежде всего я должен сказать - ЭТО СТАРЫЙ (я использую PHP 5+).Тем не менее, я сделал некоторые улучшения в нем.Прежде всего - это оболочка для FPDF библиотеки , поэтому в пакете есть файл fpdf.php.Я заменил этот файл из последней версии FPDF, которую я получил отсюда .Это сделало мои предупреждения PHP более устойчивыми.Я также изменил $pdf =& new FPDI_Protection(); и удалил знак &, поскольку получал устаревшее предупреждение для него.Тем не менее, это еще не все.Вместо того, чтобы искать и изменять код, я просто включил сообщение об ошибке lvl в 0 с помощью error_reporting(0); (хотя отключения только предупреждений должно быть достаточно).Теперь кто-то скажет, что это не «хорошая практика».Я использую весь этот материал во внутренней системе, поэтому мне не нужно беспокоиться.Конечно, сценарии могут быть изменены в соответствии с последними требованиями.Для меня я не хотел тратить другие часы, работая над этим. Будьте осторожны, когда в сценарии написано $pdf->SetProtection(array('print'), '', $password); (я разрешил печатать свои документы, как вы можете видеть).Мне потребовалось некоторое время, чтобы понять, что первый аргумент - это права доступа . секунда - ПАРОЛЬ ПОЛЬЗОВАТЕЛЯ - если вы укажете это, то для открытия документов потребуется пароль (я оставил это поле пустым). Третий - ПАРОЛЬ ВЛАДЕЛЬЦА - это то, что вам нужно, чтобы документы были "защищены" от редактирования, копирования и т. Д.

Весь мой код теперь выглядит так:

// get the HTML content of the file we want to convert
$invoice = file_get_contents("http://www.domain.com/index.php?s=invoices-print&invoice_no=".$_GET['invoice_no'];
// replace the CSS style from a print version to a specially modified PDF version
$invoice = str_replace('href="design/css/base.print.css"','href="design/css/base.pdf.css"',$invoice);

// write the modified file to disk
file_put_contents("docs/invoices/tmp/".$_GET['invoice_no'].".html", $invoice);

// do the PDF magic
exec("xvfb-run wkhtmltopdf --margin-left 16 /data/web/domain.com/web/docs/invoices/tmp/".$_GET['invoice_no'].".html /data/web/domain.com/web/docs/invoices/".$_GET['invoice_no'].".pdf");

// delete the temporary HTML data - we don't need that anymore since our PDF is created
unlink("docs/invoices/tmp/".$_GET['invoice_no'].".html");

// workaround the warnings
error_reporting(0); 

// script from ID Security Suite
function pdfEncrypt ($origFile, $password, $destFile){
    require_once('libraries/fpdf/FPDI_Protection.php');
    $pdf = new FPDI_Protection();
    $pdf->FPDF('P', 'in');
    //Calculate the number of pages from the original document.
    $pagecount = $pdf->setSourceFile($origFile);
    //Copy all pages from the old unprotected pdf in the new one.
    for ($loop = 1; $loop <= $pagecount; $loop++) {
        $tplidx = $pdf->importPage($loop);
        $pdf->addPage();
        $pdf->useTemplate($tplidx);
    }

    //Protect the new pdf file, and allow no printing, copy, etc. and
    //leave only reading allowed.
    $pdf->SetProtection(array('print'), '', $password);
    $pdf->Output($destFile, 'F');
    return $destFile;
}

//Password for the PDF file (I suggest using the email adress of the purchaser).
$password = md5(date("Ymd")).md5(date("Ymd"));
//Name of the original file (unprotected).
$origFile = "docs/invoices/".$_GET['invoice_no'].".pdf";
//Name of the destination file (password protected and printing rights removed).
$destFile = "docs/invoices/".$_GET['invoice_no'].".pdf";
//Encrypt the book and create the protected file.
pdfEncrypt($origFile, $password, $destFile );

Надеюсь, это поможет кому-то сэкономить время в будущем.Все это решение заняло у меня около 12 часов для внедрения в нашу систему выставления счетов.Если бы информация о wkhtmltopdf была лучше для таких пользователей, как я, которые не слишком знакомы с Linux / UNIX, я мог бы сэкономить некоторые часы, потраченные на это.

Однако - то, что не убивает, делает тебя сильнее :) Так что теперь я немного лучше, когда я сделал этот забег:)

...