PrestaShop PHP模块生成PDF时遇“Unable to find PDF file header”错误求助
PrestaShop PDF合并报错“Unable to find PDF file header”排查方案
核心问题:文件删除时机错误
你代码里在调用$pdf->setSourceFile($path)后立刻删除了文件,但PDF库(如TCPDF/FPDF)的importPage操作可能是懒加载逻辑——调用setSourceFile时仅读取文件头,实际页面内容读取是在importPage阶段。服务器文件I/O速度比本地慢,此时文件已被unlink删除,自然找不到PDF头。
修复:把文件删除操作移到PDF页面导入完成之后:
foreach ($order->export_invoice_url as $page=>$link) { // 用唯一文件名避免循环中文件覆盖冲突 $path = __DIR__ . '/data/pdf_' . uniqid() . '.pdf'; // 先获取远程PDF内容,增加错误判断 $pdfContent = file_get_contents($link); if ($pdfContent === false) { error_log("Failed to fetch PDF from: " . $link); continue; } file_put_contents($path, $pdfContent); $pdf->setSourceFile($path); // 完成页面导入和添加后,再删除临时文件 $tplIdx = $pdf->importPage(1); $pdf->AddPage(); $pdf->useTemplate($tplIdx, 0, 0, null, null, true); unlink($path); }
可能的其他问题及排查
1. file_get_contents获取的不是有效PDF内容
服务器环境与本地差异可能导致远程PDF获取失败,写入的是错误页面(如404、500的HTML)而非PDF:
- 检查服务器PHP配置的
allow_url_fopen是否开启(php.ini中设置为On),若禁用则改用CURL更可靠。 - 验证
$link在服务器上能否正常访问:通过SSH执行curl -I "你的PDF链接",查看返回的HTTP状态码是否为200,Content-Type是否为application/pdf。 - 增加PDF内容校验:写入文件前检查内容开头是否是
%PDF(PDF文件标准头),避免无效内容被处理:if (substr($pdfContent, 0, 4) !== '%PDF') { error_log("Invalid PDF content from: " . $link); continue; }
2. 临时文件竞争或权限细节
- 循环复用同一个文件名
pdf.pdf,可能前一次文件还未完全写入就被覆盖,导致内容不完整——改用uniqid()生成唯一文件名(如上述代码所示)。 - 确认
__DIR__/data目录权限:除读写权限外,需确保PHP进程对该目录有执行权限(通常设置为755),避免无法创建文件。
3. PDF库版本差异
本地和服务器使用的TCPDF/FPDF版本不一致,部分旧版本对文件读取逻辑有差异。可对比两边库版本,优先保持与本地一致的版本。
4. 改用CURL替代file_get_contents
若allow_url_fopen被禁用,或远程链接存在跳转、HTTPS证书问题,用CURL更稳定:
function fetchRemotePDF($url) { $ch = curl_init(); curl_setopt($ch, CURLOPT_URL, $url); curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true); // 生产环境建议配置可信证书,临时关闭SSL验证仅用于排查 curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false); $content = curl_exec($ch); $httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE); curl_close($ch); if ($httpCode !== 200 || $content === false || substr($content, 0, 4) !== '%PDF') { return false; } return $content; } // 循环中调用 $pdfContent = fetchRemotePDF($link); if (!$pdfContent) { error_log("Skipping invalid PDF: " . $link); continue; } file_put_contents($path, $pdfContent);
内容的提问来源于stack exchange,提问作者Sharkerz
相关产品推荐
相关产品推荐

