JS与PHP交互问题:Fetch等待响应时PHP输出PDF导致文件无法下载且响应异常的解决方案求助
This is a super common gotcha when using fetch for file downloads—since fetch captures the entire response body directly in your JS code instead of letting the browser handle the download natively. Let’s break down why your current setup isn’t working, then walk through two reliable solutions to get both the PDF download and a success signal for your frontend flow.
Why Your Current Code Fails
When you call $pdf->Output('D', $urlPdf), PHP sends a Content-Disposition: attachment header to trigger a download. But since this request is initiated via fetch, the browser doesn’t process that header automatically—instead, the raw PDF binary gets passed to your response.text() call as a messy string. You lose the download trigger and don’t get the clean JSON response you expect.
Solution 1: Save PDF to Server, Return Download URL
This approach is great if you need to keep a copy of the PDF on your server, or if you’re generating large PDFs (base64 can get bulky).
PHP Side (genPdf.php)
First, save the generated PDF to a server directory (make sure the directory has write permissions), then return a JSON response with the download URL and status:
<?php require('fpdf.php'); // Generate your PDF as usual $pdf = new FPDF(); $pdf->AddPage(); $pdf->SetFont('Arial','B',16); $pdf->Cell(40,10,'Hello World!'); // ... rest of your PDF generation code ... // Save PDF to server (adjust path to your needs) $uniqueFileName = 'pdf_' . uniqid() . '.pdf'; $savePath = './generated_pdfs/' . $uniqueFileName; // Create this folder first! $pdf->Output('F', $savePath); // 'F' = save to file // Send success response to JS $response = [ "pdf" => "ok", "status" => true, "downloadUrl" => "./generated_pdfs/" . $uniqueFileName // Full URL works too ]; header('Content-Type: application/json'); echo json_encode($response); ?>
JavaScript Side
Once you get the response, create a hidden <a> tag to trigger the download, then run your follow-up logic:
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) { // Trigger PDF download const downloadLink = document.createElement('a'); downloadLink.href = data.downloadUrl; downloadLink.download = 'my_custom_filename.pdf'; // Optional: rename download document.body.appendChild(downloadLink); downloadLink.click(); document.body.removeChild(downloadLink); // Run your post-download logic here console.log("PDF download started! Server response:", data); // e.g., show success message, update UI, etc. } else { console.error("Failed to generate PDF"); } } catch (error) { console.error("Server error during PDF generation:", error); } }
Solution 2: Return Base64-Encoded PDF (No Server Save)
Use this if you don’t need to store the PDF long-term—great for temporary, one-off downloads.
PHP Side
Capture the PDF as a string, convert it to base64, and send it in the JSON response:
<?php require('fpdf.php'); $pdf = new FPDF(); $pdf->AddPage(); $pdf->SetFont('Arial','B',16); $pdf->Cell(40,10,'Hello World!'); // ... PDF generation code ... // Capture PDF output as a string ob_start(); $pdf->Output('S'); // 'S' = return output as string $pdfContent = ob_get_clean(); // Encode to base64 for safe JSON transmission $pdfBase64 = base64_encode($pdfContent); $response = [ "pdf" => "ok", "status" => true, "pdfBase64" => $pdfBase64, "fileName" => "generated.pdf" ]; header('Content-Type: application/json'); echo json_encode($response); ?>
JavaScript Side
Decode the base64 string into a Blob, then trigger the download:
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) { // Decode base64 to Blob const byteChars = atob(data.pdfBase64); const byteNumbers = new Array(byteChars.length); for (let i = 0; i < byteChars.length; i++) { byteNumbers[i] = byteChars.charCodeAt(i); } const byteArray = new Uint8Array(byteNumbers); const pdfBlob = new Blob([byteArray], { type: 'application/pdf' }); // Trigger download const url = URL.createObjectURL(pdfBlob); const downloadLink = document.createElement('a'); downloadLink.href = url; downloadLink.download = data.fileName; document.body.appendChild(downloadLink); downloadLink.click(); document.body.removeChild(downloadLink); URL.revokeObjectURL(url); // Clean up memory // Run post-download logic console.log("PDF downloaded successfully!"); } else { console.error("PDF generation failed"); } } catch (error) { console.error("Server error:", error); } }
内容的提问来源于stack exchange,提问作者Lode Fabri




