
mpdf 7+ 已移除内置进度条,无法在单次请求中实时显示“处理中”状态;推荐采用前后端分离方式:前端用 fetch/ajax 触发 pdf 生成,期间显示提示文字,完成后自动下载或跳转。
mpdf 7+ 已移除内置进度条,无法在单次请求中实时显示“处理中”状态;推荐采用前后端分离方式:前端用 fetch/ajax 触发 pdf 生成,期间显示提示文字,完成后自动下载或跳转。
在 mPDF 升级至 v7 后,原 v6.x 中基于 JavaScript 动态更新的 ProgressBar 功能已被彻底移除,且底层渲染流程(HTML 解析、字体加载、布局计算、PDF 写入)均为同步阻塞操作,无法在同一个 HTTP 响应流中既输出 HTML 提示又输出 PDF 文件。因此,任何试图通过 echo + flush() 或输出缓冲控制(如 ob_flush()/flush())实现实时进度提示的方案,在实践中均会失败——要么提示不显示,要么 PDF 输出损坏或被截断。
✅ 正确解法是采用 AJAX 异步生成 + 前端状态反馈 模式:
- 用户点击按钮(如
<button id="genPdf">生成 PDF</button>),前端立即更新 UI 显示"Processing file..."; - 通过
fetch()或XMLHttpRequest向后端 PHP 脚本(如pdf.php)发起异步请求; - 后端脚本独立执行 mPDF 渲染并返回 PDF(建议使用
Content-Disposition: attachment强制下载,或返回 PDF URL); - 前端监听响应完成,更新状态为成功,并可自动触发下载或跳转。
以下为完整可运行示例:
前端 HTML + JavaScript(index.html):
<div id="status"></div>
<button id="genPdf">生成 PDF</button>
<script>
document.getElementById('genPdf').addEventListener('click', async () => {
const status = document.getElementById('status');
status.innerText = 'Processing file...';
try {
const response = await fetch('pdf.php', {
method: 'POST',
headers: { 'Content-Type': 'application/json' }
});
if (!response.ok) throw new Error(`HTTP ${response.status}`);
// 方案一:后端直接返回 PDF 流(推荐)
const blob = await response.blob();
const url = URL.createObjectURL(blob);
const a = document.createElement('a');
a.href = url;
a.download = 'document.pdf';
document.body.appendChild(a);
a.click();
document.body.removeChild(a);
URL.revokeObjectURL(url);
status.innerText = '✅ PDF 生成完成,已开始下载';
} catch (err) {
status.innerText = `❌ 生成失败:${err.message}`;
}
});
</script>
后端 PHP(pdf.php):
<?php require_once __DIR__ . '/vendor/autoload.php'; // 引入 mPDF
// 必须清除所有输出缓冲,避免干扰 PDF 二进制流
if (ob_get_level()) ob_end_clean();
$mpdf = new \Mpdf\Mpdf([
'mode' => 'utf-8',
'format' => 'A4'
]);
$html_for_pdf = '<h1>Hi, this is the HTML content to render the PDF file</h1><p>Generated at ' . date('Y-m-d H:i:s') . '</p>';
$mpdf->WriteHTML($html_for_pdf);
// 关键:设置正确 Header 并直接输出 PDF 二进制流
header('Content-Type: application/pdf');
header('Content-Disposition: attachment; filename="document.pdf"');
header('Cache-Control: no-cache');
header('Pragma: no-cache');
$mpdf->Output('', 'I'); // 'I' = inline output (to browser)
exit;
⚠️ 注意事项:
-
禁止在 PDF 生成脚本中
echo任何 HTML 或调试信息,否则 PDF 将损坏; - 若需传递参数(如用户 ID、模板类型),请通过
fetch()的body发送 JSON,后端用json_decode(file_get_contents('php://input'), true)解析; - 生产环境建议增加超时处理(
fetch({ timeout: 30000 }))和错误重试逻辑; - 对于大文件生成,可考虑将任务放入队列(如 Redis + Worker),前端轮询状态,提升用户体验。
该方案完全规避了 PHP 输出缓冲与 PDF 二进制流的冲突,符合现代 Web 架构规范,稳定可靠,是 mPDF v7+ 下实现“进度提示”的唯一推荐实践。










