Fetch请求等待PHP响应时PDF下载与结果返回冲突问题求助
解决方案:同时实现PDF下载与任务完成响应
方案一:分两次请求(推荐,避免大文件传输问题)
先请求PHP生成PDF并返回成功状态,再触发文件下载:
前端代码
async function genPdf() { try { // 第一步:请求生成PDF并获取状态 const statusResponse = await fetch('genPdfStatus.php', { method: 'POST', headers: { 'Content-Type': 'application/json' } }); const statusData = await statusResponse.json(); if (statusData.status) { console.log("PDF生成成功,开始下载"); // 第二步:触发下载,用a标签实现 const downloadLink = document.createElement('a'); downloadLink.href = `downloadPdf.php?file=${statusData.fileName}`; downloadLink.download = statusData.fileName; document.body.appendChild(downloadLink); downloadLink.click(); document.body.removeChild(downloadLink); // 这里执行后续操作 console.log("下载已触发"); } else { console.log("PDF生成失败"); } } catch (error) { console.log("请求出错:", error); } }
后端代码(genPdfStatus.php)
<?php require('fpdf.php'); $pdf = new FPDF(); // ... 此处添加PDF内容生成逻辑 ... // 生成唯一文件名,保存到临时目录 $fileName = uniqid('pdf_') . '.pdf'; $tempPath = './temp_pdfs/' . $fileName; // 确保临时目录存在 if (!is_dir('./temp_pdfs/')) { mkdir('./temp_pdfs/', 0755, true); } // 保存PDF到服务器 $pdf->Output('F', $tempPath); // 返回状态和文件名 $result = array("pdf" => "ok", "status" => true, "fileName" => $fileName); header('Content-Type: application/json'); echo json_encode($result); ?>
后端代码(downloadPdf.php)
<?php $fileName = $_GET['file'] ?? ''; $tempPath = './temp_pdfs/' . $fileName; if (file_exists($tempPath)) { // 设置下载头 header('Content-Type: application/pdf'); header('Content-Disposition: attachment; filename="' . $fileName . '"'); header('Content-Length: ' . filesize($tempPath)); // 输出文件内容 readfile($tempPath); // 删除临时文件(可选,根据需求保留) unlink($tempPath); } else { header("HTTP/1.0 404 Not Found"); echo "文件不存在"; } ?>
方案二:一次请求返回Base64编码的PDF
适合小体积PDF,前端解码后触发下载:
前端代码
async function genPdf() { try { const response = await fetch('genPdf.php', { method: 'POST', headers: { 'Content-Type': 'application/json' } }); const data = await response.json(); if (data.status) { // 解码Base64为Blob const pdfBlob = new Blob([Uint8Array.from(atob(data.pdfBase64), c => c.charCodeAt(0))], { type: 'application/pdf' }); // 创建下载链接 const downloadLink = document.createElement('a'); downloadLink.href = URL.createObjectURL(pdfBlob); downloadLink.download = 'generated.pdf'; document.body.appendChild(downloadLink); downloadLink.click(); document.body.removeChild(downloadLink); URL.revokeObjectURL(downloadLink.href); // 释放资源 console.log("PDF下载完成"); // 执行后续操作 } else { console.log("PDF生成失败"); } } catch (error) { console.log("请求出错:", error); } }
后端代码(genPdf.php)
<?php require('fpdf.php'); $pdf = new FPDF(); // ... 此处添加PDF内容生成逻辑 ... // 获取PDF的字符串内容('S'参数返回字符串) $pdfContent = $pdf->Output('S'); // 转成Base64编码 $pdfBase64 = base64_encode($pdfContent); // 返回状态和Base64内容 $result = array("pdf" => "ok", "status" => true, "pdfBase64" => $pdfBase64); header('Content-Type: application/json'); echo json_encode($result); ?>
方案三:用表单提交代替Fetch(适合简单场景)
直接用表单提交触发下载,PHP可通过脚本通知前端任务完成:
前端代码
<form id="pdfForm" action="genPdf.php" method="POST" style="display:none"> <!-- 需要传递参数可添加隐藏输入框 --> </form> <script> function genPdf() { document.getElementById('pdfForm').submit(); // 可通过PHP返回的脚本提示确认完成 } </script>
后端代码(genPdf.php)
<?php require('fpdf.php'); $pdf = new FPDF(); // ... 此处添加PDF内容生成逻辑 ... // 触发下载 $pdf->Output('D', 'generated.pdf'); // 输出脚本提示成功(注意:下载头发送后,部分浏览器可能不显示此内容,可根据需求调整) echo '<script>console.log("PDF生成并下载成功");</script>'; ?>
内容的提问来源于stack exchange,提问作者Lode Fabri
相关产品推荐
相关产品推荐

