4

我正在尝试使用 dompdf 将较大的 html 表呈现为 pdf。有最小的 css 样式,但表中可能有 200 - 300 行。每行有 4 个带有基本文本的 td。

我可以毫无问题地生成一个较小表的 pdf,但较大的表会耗尽内存限制并且脚本将终止。解决这个问题的最佳方法是什么?我开始讨论 serverfault,一位用户建议生成一个新进程,以免耗尽 php / apache 的内存限制?这是最好的方法吗?这让我产生了关于它如何工作的问题,因为 dompdf 当前将下载流式传输到浏览器,但我假设如果我创建一个新进程来生成报告,我不能再将输出发送到浏览器用户下载?

感谢任何可能提出解决此问题的好方法的人!

4

2 回答 2

3

如果您使用辅助 PHP 进程(例如使用exec())呈现您的 HTML,则执行时间和内存限制会得到缓解。以这种方法渲染时,您将渲染的 PDF 保存到网站上的目录中,并将用户重定向到下载(如果您想运行渲染队列,甚至可以通过电子邮件向他们发送链接)。一般来说,我发现这种方法确实在速度和内存使用方面提供了适度的改进。

但是,这并不意味着渲染在您的情况下会执行得更快。目前使用 dompdf 渲染表是资源密集型的。如果可以的话,可能会更好的方法是将文档分成几部分,分别渲染每个部分(再次使用辅助 PHP 进程),将生成的 PDF 集合合并到一个文件中(使用类似 pdftk 的东西),然后将 PDF 保存在用户可以访问的地方。我已经看到使用这种方法显着提高了性能。

或者使用 wkhtmltopdf 之类的东西(如果您可以通过 shell 访问您的服务器并且愿意处理安装过程)。

于 2013-04-24T22:31:35.040 回答
2

我在处理许多不同的生成文件类型时遇到了这个问题,而不仅仅是 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.';
}

因为生成文件需要一段时间,所以回声一个接一个地出现,让用户可以看到一些东西,所以他们不会认为屏幕已经冻结。最终的回显链接只会在文件生成后出现,这意味着用户会自动等待文件准备好才能下载。您可能必须延长此脚本的最大执行时间。

于 2013-04-24T22:17:14.747 回答