我试图用dompdf渲染一个较大的html表到pdf。有最小的css样式,但可能200 - 300行在表中。每行有4个带有基本文本的td。
我可以生成一个较小的表的pdf没有问题,但一个较大的表将耗尽内存限制,脚本将终止。解决这个问题的最佳方法是什么?我在serverfault上开始了一个讨论,一个用户建议生成一个新的进程,以便不耗尽php/apache的内存限制?这是最好的办法吗?这让我产生了关于如何工作的问题,在dompdf当前将下载流式传输到浏览器中,但是我假设如果我创建一个新流程来生成报告,我就不能再将输出发送到浏览器以供用户下载了?
感谢任何可能提出解决这个问题的好方法的人!
如果使用二级PHP进程(例如使用exec()
)呈现HTML,则执行时间和内存限制将得到缓解。在用这种方法呈现时,您将呈现的PDF保存到网站上的一个目录中,并将用户重定向到下载处(如果您想运行呈现队列,甚至可以通过电子邮件向用户发送链接)。一般来说,我发现这种方法确实在速度和内存使用方面提供了适度的改进。
或者使用wkhtmltopdf(如果您有访问服务器的shell权限并且愿意处理安装过程)。
我在生成许多不同类型的文件时都遇到过这个问题,而不仅仅是pdf。生成进程没有帮助,因为问题在于变量的大小,无论进程多么新鲜,变量仍然太大。我的解决方案是创建一个文件,并在可管理的块中写入它,这样我的变量就不会超过一定的大小。
一个基本的,未经测试的例子:
$tmp = fopen($tmpfilepath, 'w');
if(is_resource($tmp)) {
echo 'Generating file ... ';
$dompdf = new DOMPDF();
$counter = 0;
$html = '';
while($line = getLineOfYourHtml()) {
$html .= $line;
$counter++;
if($counter%200 == 0) { //pick a good chunk number here
$dompdf->load_html($html);
$dompdf->render();
$output = $dompdf->output();
fwrite($tmp, $output);
echo round($counter/getTotalLines()).'%... '; //echo percent complete
$html = '';
}
}
if($html != '') { //the last chunk
$dompdf->load_html($html);
$dompdf->render();
$output = $dompdf->output();
fwrite($tmp, $output);
}
fclose($tmp);
if(file_exists($tmpfilepath)) {
echo '100%. Generation complete. ';
echo '<a href="'.$tmpfileURL.'">Download</a>';
} else {
echo ' Generation failed.';
}
} else {
echo 'Could not generate file.';
}
因为生成文件需要一段时间,所以回声一个接一个地出现,给用户一些东西看,这样他们就不会认为屏幕已经冻结了。最后的回显链接只会在文件生成之后出现,这意味着用户会自动等待,直到文件准备好,然后才能下载它。您可能需要延长此脚本的最大执行时间。