PHP中的HTML2PDF-转换实用程序&;脚本-示例&;演示


HTML2PDF in PHP - convert utilities & scripts - examples & demos

我有一个非常复杂的HTML/CSS布局,我想在服务器上将其转换为PDF。我已经尝试过DOMPDF,不幸的是它没有用正确的布局转换HTML。我考虑过HTMLDOC,但我听说它在很大程度上忽略了CSS,所以我想这个工具也会破坏布局。

我的问题是,有没有其他工具的在线演示(比如wkhtmltopdf)可以用来验证我的HTML是如何转换的?在我度过余生之前安装&逐一测试?

不幸的是,我无法更改HTML布局以适应这些工具。或者更好地说——我可以,如果他们中的任何一个能接近一个可以接受的结果。。。

这不是一个真正的答案,但对于上面的问题,我会尝试提供一些我的经验,也许它会在未来的某个地方对某人有所帮助。

  1. wkthmltopdf实际上是唯一对我有效的解决方案,它可以产生我所说的可接受的结果。尽管如此,还是需要对CSS进行一些小的修改,然而,在呈现内容时,它确实很好。只有当你有一个相当简单的文档和一个基本表等时,所有其他包才真正适合。没有机会让它们在具有设计元素、css、多个重叠图像等的复杂文档上产生公平的结果。如果复杂文档在游戏中-不要花时间(像我一样)-直接访问wkhtmltopdf

  2. 小心-wkhtmltopdf的安装很棘手。这对我来说并不像那些家伙在评论中所说的那样容易(其中一个原因可能是我对Linux不太熟悉)。由于某些原因,静态二进制文件对我不起作用,我无法解释。我怀疑这个版本有问题——显然不同操作系统和处理器的版本之间存在差异,也许我有vrong版本。对于安装非静态版本,首先您必须拥有对服务器的root访问权限,这是显而易见的我使用PuTTyapt-get中安装了它,运行得很好。我很幸运,我的服务器已经具备了安装wkhtmltopdf的所有能力。所以这对我来说是简单的部分:)(顺便说一句,你不必像许多教程告诉你的那样关心符号链接或包装——我花了几个小时试图弄清楚如何做这部分,最后我放弃了,但一切都很好)

  3. 安装后我得到了非常著名的Cannot connect to X server错误。这是因为我们需要在"虚拟"x服务器上运行wkhtmltopdf headless。绕过这一点也很简单(如果不关心符号链接的话)我用apt-get install xvfb安装了它。这对我来说也很顺利,没有问题。

  4. 完成此操作后,我可以运行wkhtmltopdf。小心——我花了一些时间才发现尝试运行xvfb是错误的方式——相反,您必须运行xvfb-run。我的PHP代码现在看起来像这个exec("xvfb-run wkhtmltopdf --margin-left 16 /data/web/example.com/source.html /data/web/example.com/target.pdf");(注意wkhtmltopdf--margin-left 16命令行选项-它使我的内容更加集中;我将其保留在原位,以演示如何使用命令行选项)。

  5. 我还想保护生成的PDF文件不受编辑(在我的情况下,打印保护也是可能的)。经过一些研究,我在ID Security Suite中找到了这个类。首先我要说的是-它很旧(我正在运行PHP5+)。然而,我对它做了一些改进。首先,它是FPDF库的包装器,所以包中有一个名为FPDF.php的文件。我从这里得到的最新FPDF版本中替换了这个文件。它使我的PHP警告看起来更加可持续。我还更改了$pdf =& new FPDI_Protection();并删除了&符号,因为我收到了一个不推荐使用的警告。然而,还会有更多这样的警告。我没有搜索和修改代码,而是使用error_reporting(0);将错误报告级别l设置为0(尽管只关闭警告就足够了)。现在有人会说这不是";良好实践";。我在内部系统中使用这些东西,所以我真的不必在意。当然,可以修改脚本以满足最新的要求。对我来说,我不想再花几个小时来处理它。小心脚本上写着$pdf->SetProtection(array('print'), '', $password);的地方(正如你所看到的,我允许打印我的文档)。我花了一段时间才弄清楚第一个参数是权限第二个是USER PASSWORD-如果您提供了这个密码,那么文档将需要一个密码才能打开(我将其留空)第三个是所有者密码-这是制作文档所需的内容"有担保";防止编辑、复制等

我的整个代码现在看起来像:

// get the HTML content of the file we want to convert
$invoice = file_get_contents("http://www.example.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 do not 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个小时才在我们的发票系统中实现。如果像我这样不太熟悉Linux/UNIX的用户在wkhtmltopdf上有更好的信息,我本可以节省一些时间。

然而,没有杀死你的东西会让你变得更强大:)所以我现在跑得更完美了:)