Как массово генерировать PDF из HTML шаблонов, готовых для двусторонней печати на PHP?

я боролся с этим некоторое время и чувствую себя беспомощным. Prestashop использует tcpdf для создания счетов-фактур и накладных доставки из HTML-шаблонов, заполненных с помощью Smarty. Мы работаем над обновлением дизайна счета-фактуры и обнаружили, что tcpdf не хватает поддержки CSS. После некоторых исследований мы остановились на wkhtmltopdf как правильный инструмент для преобразования шаблонов HTML / CSS в PDF.

проблема

магазин имеет функцию экспорта нескольких счетов-фактур в один PDF-файл. Используя TCPDF я смог сделать пакетный файл готовым к двусторонней печати, вставив пустую страницу после каждого счета, который имел нечетное количество страниц до создания файла. Но теперь, когда мы перешли на wkhtmltopdf Я не могу достичь того же результата.

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

Я также попытался вычислить height of the content / PDF page height но были различные вопросы С этим, как только я начал экспортировать несколько шаблонов (работал хорошо с одним шаблоном). Этот подход это тоже не здорово, потому что вставка пустой страницы в сам контент заставляет нижний колонтитул появляться на новой странице, а это не то, что я хочу.

моя лучшая попытка

единственный способ, которым я понял, что может помочь мне обойти эти проблемы, очень неэффективен. Каждый раз, когда шаблон добавляется в пакет, я могу предварительно сгенерировать его, используя отдельный экземпляр фантик на wkhtmltopdf, получить имя временного файла, определить, сколько страниц с помощью pdfinfo и добавьте пустой шаблон HTML в основной экземпляр соответственно. Вот проект функции, чтобы получить количество страниц последнего добавленного шаблона (из класса, который расширяет оболочку, на основе некоторых других 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;
}

это очень неэффективно - это занимает около 80 секунд, чтобы создать партию из 25 счетов-фактур, потому что я должен позвонить wkhtmltopdf 25 раз для создания временных файлов PDF так что я могу позвонить pdfinfo 25 раз, чтобы получить их отдельные длины и вставить пустые страницы, где это необходимо, а затем создать окончательный документ.

преимущество TCPDF заключается в том, что он может дать вам количество страниц на лету, и аналогичная функциональность занимает около 5 секунд для создания пакетного файла из 25 счетов-фактур.

у кого-нибудь есть идеи о том, как ускорить процесс? Или лучше сделать это вообще. Я рассмотрел различные инструменты для генерации в том числе dompdf, но wkhtmltopdf просто самый мощный. Пакетная генерация действительно используется только из бэк-офиса администраторами магазина, поэтому, возможно, они могут быть терпеливы. Но все же ...

1 ответов


к сожалению wkhtmltopdf библиотека, которая написана на языке C и мы не можем динамически добавлять одну страницу на лету, как в PHP библиотеки.

цитата из вашего комментария: должный к количеству деталей приказал или ammount данных по клиента каждая фактура может находиться везде от 1 до 3 страницы длиной.

и из-за этого мы не можем заранее рассчитать количество страниц и напиши база данных.

Я думаю, у вас есть только одна из возможностей / решение: вы должны написать за каждой накладной пустую страницу, и после того, как весь PDF был сгенерирован, вы должны отредактировать его с помощью бесплатной библиотеки PHP, такой как FPDI. В сочетании с FPDI можно даже редактировать PDF документы.

при редактировании PDF вы можете удалить все пустые страницы, которые вам не нужны, если они начинаются с нечетного номера страницы (например,3, 5, etc.). И в 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();
?>

мой 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();
?>