【问题标题】:Can't get rid of PHP notices in mPDF无法摆脱 mPDF 中的 PHP 通知
【发布时间】:2012-02-22 11:35:55
【问题描述】:

我正在使用mPDF library 直接从 HTML 输出生成 PDF 文档。问题是这个 mPDF 库是按原样编写的,它会生成许多通知(未定义的索引、未定义的偏移量等)。我尝试了任何方法来停止输出它们,但没有任何帮助。

我尝试将error_reporting(E_ALL ^ E_NOTICE);error_reporting(E_ALL & ~E_NOTICE); 插入到我的index.php 中,放入直接包含mpdf.php 的类和方法中以及mpdf.php 的开头。我还尝试了与ini_set('display_errors', 0); 的组合——所有这些指令都适用于整个 Web 应用程序,但适用于 mpdf。因此,即使 PDF 格式正确且有效,我也无法输出(让用户下载)。

我的 HTML 也出现了问题(简单的表格,真的没什么特别的),而示例工作正常且没有任何通知。

所以我需要的帮助是:要么摆脱通知,要么更好地帮助我找出为什么 mPDF 不适合我。

如果我使用此代码:

include_once(DIR_MPDF.'mpdf.php');
$mpdf = new mPDF();
$mpdf->useOnlyCoreFonts = true;
$mpdf->SetDisplayMode('fullpage');
$mpdf->SetAutoFont(0);
$mpdf->WriteHTML('<table><tr><td>HELLO WORLD</td></tr></table>');
$mpdf->Output();
exit;

一切正常,但如果我尝试输出此 HTML:

$mpdf->WriteHTML('<table><tr><td>HELLO WORLD</td><td>HELLO WORLD</td></tr></table>');

我收到通知,因此无法输出 PDF。

如果我将 mPDF 的输出保存到文件中(使用例如 file_put_contents()),即使我使用复杂的 HTML,PDF 也是有效的,因此可读 - 但通知仍会打印到浏览器中。无论如何,我需要提供 PDF 以供下载,而不是保存到文件系统中。

好的,我找到了一种解决方案,尽管它不是最佳实践(但它有效):我用ob_start();ob_end_clean(); 将代码括起来,同时找出我输出的$pdf 字符串而不是mPDF。

最终代码:

ob_start();
include(DIR_MPDF.'mpdf.php');
$html = $this->render(TRUE);

$mpdf = new mPDF('utf-8','A4');

$mpdf->useOnlyCoreFonts = true;
$mpdf->SetDisplayMode('fullpage');
$mpdf->SetAutoFont(0);

$stylesheet = file_get_contents(DIR_APPLICATION.'view/stylesheet/declaration.css');
$mpdf->WriteHTML($stylesheet,1);

$mpdf->WriteHTML($html);

$pdf = $mpdf->Output('', 'S');
$ob = ob_get_contents();
ob_end_clean();

if (headers_sent())
    die('Some data has already been output to browser, can\'t send PDF file');
header('Content-Description: File Transfer');
header('Content-Transfer-Encoding: binary');
header('Cache-Control: public, must-revalidate, max-age=0');
header('Pragma: public');
header('Expires: Sat, 26 Jul 1997 05:00:00 GMT');
header('Last-Modified: '.gmdate('D, d M Y H:i:s').' GMT');
header('Content-Type: application/force-download');
header('Content-Type: application/octet-stream', false);
header('Content-Type: application/download', false);
header('Content-Type: application/pdf', false);
if (!isset($_SERVER['HTTP_ACCEPT_ENCODING']) OR empty($_SERVER['HTTP_ACCEPT_ENCODING'])) {
    header('Content-Length: '.strlen($pdf));
}
header('Content-disposition: attachment; filename="invoice.pdf"');
echo $pdf;
exit;

【问题讨论】:

  • 可能 mPDF 在被调用时正在改变错误级别/报告?您可以尝试通过将@ 运算符与有问题的表达式一起使用来抑制错误,但这不是好的做法。可能有库的更新或配置设置? (我不知道 mPDF)
  • @hakre,没有这样的设置(AFAIK),但我会试试@符号。
  • @shaddyyx:确保不会因为您的输入而发出警告。只是说,你的代码看起来很干净,可能是 HTML 不可接受?
  • @hakre,没有警告。请注意...并且它们在 mPDF 尝试发送它的标题或它们成为 PDF 文档的一部分之前被输出,因此它是不可读的。
  • 不是答案:您是否考虑过使用不同的 HTML 到 PDF 技术? wkhtmltopdf 受到很好的推荐,它包含适用于大多数环境的预编译二进制文件(这使得它可以在许多共享主机帐户上使用)。

标签: php notice mpdf


【解决方案1】:

虽然没有答案,而且因为我还没有找到任何其他合适的解决方案,但这里是我到目前为止的总结(主要是从我上面的问题复制而来):

ob_start(); // <--| This is very important to start output buffering and to catch out any possible notices
include(DIR_MPDF.'mpdf.php');
$html = $this->render(TRUE);

$mpdf = new mPDF('utf-8','A4');

$mpdf->useOnlyCoreFonts = true;
$mpdf->SetDisplayMode('fullpage');
$mpdf->SetAutoFont(0);

$stylesheet = file_get_contents(DIR_APPLICATION.'view/stylesheet/declaration.css');
$mpdf->WriteHTML($stylesheet,1); // <--| By the second param we are saying to MPDF that it is icnluding only stylesheet

$mpdf->WriteHTML($html);

$pdf = $mpdf->Output('', 'S'); // <--| With the binary PDF data in $pdf we can do whatever we want - attach it to email, save to filesystem, push to browser's PDF plugin or offer it to user for download
$ob = ob_get_contents(); // <--| Here we catch out previous output from buffer (and can log it, email it, or throw it away as I do :-) )
ob_end_clean(); // <--| Finaly we clean output buffering and turn it off

// The next headers() section is copied out form mPDF Output() method that offers a PDF file to download
if (headers_sent())
    die('Some data has already been output to browser, can\'t send PDF file');
header('Content-Description: File Transfer');
header('Content-Transfer-Encoding: binary');
header('Cache-Control: public, must-revalidate, max-age=0');
header('Pragma: public');
header('Expires: Sat, 26 Jul 1997 05:00:00 GMT');
header('Last-Modified: '.gmdate('D, d M Y H:i:s').' GMT');
header('Content-Type: application/force-download');
header('Content-Type: application/octet-stream', false);
header('Content-Type: application/download', false);
header('Content-Type: application/pdf', false);
if (!isset($_SERVER['HTTP_ACCEPT_ENCODING']) OR empty($_SERVER['HTTP_ACCEPT_ENCODING'])) {
    header('Content-Length: '.strlen($pdf));
}
header('Content-disposition: attachment; filename="invoice.pdf"');
echo $pdf; // <--| With the headers set PDF file is ready for download after we call echo
exit;

正如上面评论中所写,然后我(或客户:-))将如何处理从 mPDF 返回的 PDF 数据。我通过应用程序在更多地方使用此 PDF 生成,并且主要提供 PDF 供下载,但我也将其附加到电子邮件中(用户付款,我生成 PDF 发票并通过电子邮件发送)。

我没有找到解决方案(也没有更多时间这样做)来阻止 mPDF 生成通知,并且我还没有失去“修复” mpdf.php(及其 1.34 MB 的 PHP 代码)的想法。这是(目前)唯一适合我的解决方案。

也许它会对某人有所帮助。

【讨论】:

  • @shadyx 你有没有找到另一种解决方案 - 虽然我的 PDF 格式正确(但我收到很多我想摆脱的通知),但我也遇到了类似的问题
  • @torr 对不起,我没有。只有使用输出缓冲,我才能摆脱 PHP Notice 消息并正确输出 PDF...
  • 通知在 MPDF 6.x 中消失了吗?
【解决方案2】:

似乎错误发生在它试图为每一页写出新的表格标题时。 我在 V 5.4 中注释掉了 第 26210 行

#$this->TableHeaderFooter($tablefooter,$tablestartpage,$tablestartcolumn,'F',$level, $firstSpread, $finalSpread);   // mPDF 5.3.36

不管怎样注释掉这一行,标题都没有被绘制出来,除了取消通知之外没有任何效果。

【讨论】:

    【解决方案3】:

    如果您在ob_end_clean() 之后使用$mpdf-&gt;Output(),您甚至可以在浏览器中无提示地显示PDF!我在 OpenCart 中使用它。但是您需要使用ob_start()ob_end_clean()

    【讨论】:

    • 感谢您的回答,但您能说出您的答案与接受的答案有什么不同吗?它非常简短,没有任何代码示例,并且在一年半之后......
    • 我找到了你的答案,但你使用 $pdf = $mpdf->Output('', 'S');在 ob_end_clean 之前,我将它用于电子邮件中的 pdf。但是,如果您在 ob_end_clean 之后使用 $mpdf->Output() ,则通知也会消失,您可以在浏览器中显示 pdf 而无需通知。从您的回答中,这不是很清楚..您只在示例中写了有关下载的内容..
    猜你喜欢
    • 1970-01-01
    • 2016-11-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-06-26
    • 2021-10-22
    相关资源
    最近更新 更多