如何从HTML模板批量生成PDF,以便在PHP中进行双面打印?

Pet*_*ter 10 php pdf wkhtmltopdf prestashop-1.5

我一直在努力奋斗,感到无助.Prestashop使用tcpdf从使用Smarty填充的HTML模板生成发票和交付单.我们正在努力更新发票设计,发现缺少CSS支持的tcpdf.经过一些研究,我们决定将wkhtmltopdf作为将HTML/CSS模板转换为PDF的正确工具.

问题

该商店具有将多个发票导出为单个PDF的功能.使用TCPDF我能够通过在生成文件之前具有奇数页数的每张发票之后插入空白页来使批处理文件准备好进行双面打印.但是现在我们切换到了wkhtmltopdf我无法达到同样的效果.

关键问题是,虽然wkhtmltopdf允许使用多个HTML模板,但似乎没有可靠的方法来确定在生成文件之前它们将具有的页数.页眉和页脚模板可以接收发票最终的页数,但它们与主要内容分开,因此我无法相应地插入分页符.

我也尝试计算height of the content/ PDF page height但是一旦我开始导出多个模板就会出现各种问题(使用单个模板可以正常工作).这种方法不是很好,因为在内容中插入空白页本身也会导致页脚出现在新页面上,这不是我想要的.

我最好的尝试

我发现的唯一方法可能让我解决这些问题是非常低效的.使用的一个单独的实例每个模板添加到批我可以一次预先生成它包装wkhtmltopdf,得到了临时文件名,确定它有多少页中使用pdfinfo,并相应地添加一个空白HTML模板到主实例.这是一个函数的草稿,用于获取添加的最后一个模板的页面数(从扩展包装器的类,基于我在SO上找到的其他一些pdfinfo 问题):

/**
* Return the number of pages in the last invoice template added
* $complete === true => return the length of the entire document
*/
public function getNumPages($complete = false)
{
    if (!$complete) {
        // Generate PDF of last template added

        $tmpPdf = new WKPdf($this->_options);
        $tmpPdf->addPage($this->content, Array(
            'footer-html' => $this->footer
        ));

        /**
           The createPdf method is protected so I need to get 
           the content as string here to force the wrapper to 
           call wkhtmltopdf.
        */
        $tmpPdf->toString();
        $document = $tmpPdf->getPdfFilename();
    } else {

        // Generate entire batch
        $this->createPdf();
        $document = $this->getPdfFilename();
    }

    // Use pdfinfo to get the PDF page count
    $cmd = 'pdfinfo';
    exec("$cmd \"$document\"", $output);

    $pagecount = 0;
    foreach($output as $op)
    {
        // Extract the number
        if(preg_match("/Pages:\s*(\d+)/i", $op, $matches) === 1)
        {
            $pagecount = intval($matches[1]);
            break;
        }
    }

    return $pagecount;
}
Run Code Online (Sandbox Code Playgroud)

这是非常低效的 - 生成一批25张发票需要大约80秒,因为我必须调用wkhtmltopdf25次来创建临时PDF文件,以便我可以调用pdfinfo25次来获取他们各自的长度并在必要时插入空白页然后生成最终文档.

TCPDF的优点是它可以动态提供页面数量,类似的功能大约需要5秒钟来生成25个发票的批处理文件.

任何人对如何加快速度都有任何想法?或者更好的想法完全这样做.我已经考虑了生成的各种工具,包括dompdf,但wkhtmltopdf只是最强大的.批量生成实际上只能由商店管理员从后台使用,所以也许他们可能有耐心.但仍然.

Bha*_*ata 2

不幸的是wkhtmltopdf是用 C 语言编写的库,我们无法像 PHP 库那样动态添加一页。

引用您的评论: 由于订购的商品数量或客户数据量,每张发票的长度可能为 1 到 3 页。

因此我们无法预先计算页数并将其写入数据库。

我认为你只有一种可能性/解决方案:你必须在每张发票后面写一个空白页,生成整个 PDF 后,你必须使用免费的 PHP 库(如FPDI )对其进行编辑。与 FPDI 结合,甚至可以编辑 PDF 文档。

3通过 PDF 编辑,您可以删除所有以奇数页码开头(如、5等)不需要的空白页。在 FPDI 中,您可以检测页码。它比您现在使用的解决方案快得多。

您可以使用 FPFI检测内容长度上的空白(或空白)页面,如下所示:

<?php
require('fpdf.php');
require_once('setasign/Fpdi/autoload.php');

class Pdf extends \setasign\Fpdi\Fpdi
{
    private $pdfReader;
    function Header()
    {
        if(is_null($this->pdfReader))
        {
            $readerId = $this->getPdfReaderId('blank-pages.pdf');
            $this->pdfReader = $this->getPdfReader($readerId);
        }

        $page_fpdi = $this->pdfReader->getPage($this->PageNo());
        $this->content = $page_fpdi->getContentStream();

        $this->Cell(0, 15, 'page content length: '.strlen($this->content));
    }

    protected function _putimages(){}
}

$pdf = new Pdf();
$pdf->SetFont('Arial', '', 12);
$pdf->AddPage(); //page content length: 70 // page with 'Hello World!' string
$pdf->AddPage(); //page content length: 30 // empty page
$pdf->AddPage(); //page content length: 30 // empty page
$pdf->Output();
?>
Run Code Online (Sandbox Code Playgroud)

blank-pages.pdf已经使用 FPDF 生成了以下代码:

<?php
require('fpdf.php');

$pdf = new FPDF();
$pdf->AddPage();
$pdf->SetFont('Arial','B',16);
$pdf->Cell(40,10,'Hello World!');
$pdf->AddPage();
$pdf->AddPage();
$pdf->Output();
?>
Run Code Online (Sandbox Code Playgroud)