PDF输出方式由output参数动态控制:output=download强制下载,否则浏览器预览;需过滤用户数据防XSS,按Accept-Language自动适配多语言字体;模板非法时返回400或404状态码。

动态控制PDF输出方式:浏览器预览 or 附件下载
生成PDF时需根据业务场景自动决定是让用户在浏览器中直接查看,还是强制触发下载弹窗——比如后台预览报表用预览模式,导出存档则必须下载。
第一步:从请求参数识别意图,优先检查output键,缺失时默认走预览:$output_mode = $_GET['output'] ?? 'inline';
第二步:用三元运算符映射html2pdf的output()方法参数:$pdf->output('report.pdf', $output_mode === 'download' ? 'D' : 'I');。注意'D'表示下载,'I'表示内嵌预览,【传错字符如'd'或'DOWNLOAD'会导致静默失败并输出空白响应】。
第三步:若需兼容旧版TCPDF,其参数为字符串而非单字母,此时改用分支更清晰:$tcpdf_output_type = $output_mode === 'download' ? 'D' : ($output_mode === 'file' ? 'F' : 'I');。
立即学习“PHP免费学习笔记(深入)”;
PDF模板中安全渲染用户数据
将动态字段插入PDF HTML模板前,必须过滤空值、防止DOM断裂或内容泄露。
方法一:用空合并+三元组合清洗字段
提取订单号和用户名:$order_id = $_GET['id'] ?? ''; → $name = $_POST['name'] ?? ''; → 拼接时用?:兜底:$html = "<h2>订单 #".($order_id ?: 'N/A')."</h2>
<p>客户:".($name ?: '未填写')."</p>";。这一步不能用isset()替代——【当$name为字符串'0'时,isset($name)为true但$name ?: 'guest'会误判为false,导致错误替换】。
方法二:对敏感字段做存在性+非空双重校验$phone = ($_GET['phone'] ?? '') !== '' ? htmlspecialchars($_GET['phone']) : '保密';。这里先用??避免未定义索引警告,再用!== ''排除空字符串,最后转义防XSS注入。
多语言PDF字体自动适配
中文、日文、阿拉伯文等需不同字体文件,而FPDF/mpdf/tcPDF的字体加载逻辑差异大,需统一抽象。
① 判断客户端语言偏好(从Accept-Language头提取主语言):$lang = substr($_SERVER['HTTP_ACCEPT_LANGUAGE'] ?? 'en', 0, 2);
② 用三元链式匹配字体族名:$font_family = $lang === 'zh' ? 'simsun' : ($lang === 'ja' ? 'msmincho' : ($lang === 'ar' ? 'dejavusans' : 'helvetica'));
③ 根据PDF库类型选择加载方式:
若用mpdf:$mpdf = new \Mpdf\Mpdf(['default_font' => $font_family]);
若用TCPDF:$pdf->setLanguageArray($lang === 'zh' ? TCPDF_FONTS::getFontData('ch') : []); → 再调用$pdf->setFont($font_family);。
这一步跳过语言检测直接硬编码字体,会导致非中文用户看到方块字。
PDF生成失败时返回对应HTTP状态码
用户提交非法参数(如超长文本、不存在的模板ID)时,不能只输出空白页或500错误,要明确告知客户端错误类型。
提取模板ID:$template = $_GET['tpl'] ?? null;
判断是否存在且合法:$is_valid = $template && in_array($template, ['invoice', 'receipt', 'contract']);
用三元运算符映射HTTP状态:http_response_code($is_valid ? 200 : ($template === null ? 400 : 404));。
注意:400代表参数缺失,404代表模板不存在,【状态码必须在任何PDF输出之前调用,否则header已发送会报Warning】。



















