Как массово генерировать 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();
?>