Next.js 13中点击按钮触发POST请求下载PDF失败问题
解决Next.js 13中POST请求触发PDF下载的问题
问题核心在于fetch请求不会自动识别Content-Disposition: attachment响应头:浏览器直接导航(比如<Link>发起的GET请求)会自动触发下载,但脚本发起的fetch请求需要手动处理返回的Blob数据才能完成下载。另外你的客户端请求头存在错误——POST的body是JSON格式,却设置了Content-type: application/pdf,这会导致后端无法正确解析请求体,需要先修正这个问题。
修改客户端组件代码
更新generatePdf函数,在获取响应后手动处理Blob并触发下载:
function generatePdf() { fetch("/api/generate-pdf", { method: "POST", headers: { // 修正请求头:发送JSON数据需用该类型 "Content-Type": "application/json", }, body: JSON.stringify(store), }) .then(async (res) => { if (!res.ok) throw new Error("PDF生成请求失败"); // 将响应转换为Blob对象 const blob = await res.blob(); // 创建临时下载URL const downloadUrl = window.URL.createObjectURL(blob); // 创建临时a标签触发下载 const link = document.createElement("a"); link.href = downloadUrl; // 设置文件名(也可从响应头动态解析) link.download = "pac.pdf"; document.body.appendChild(link); link.click(); // 清理临时资源 link.remove(); window.URL.revokeObjectURL(downloadUrl); }) .catch((err) => { console.error("生成PDF出错:", err); // 可在此添加用户可见的错误提示,比如alert或组件提示 }); } <Button onClick={generatePdf} type="button"> Generate PDF </Button>
补充:动态解析后端返回的文件名
如果不想在客户端硬编码文件名,可以从响应头中解析后端返回的Content-Disposition字段:
// 在获取blob后添加这段代码 const dispositionHeader = res.headers.get("Content-Disposition"); let filename = "pac.pdf"; if (dispositionHeader) { const filenameMatch = dispositionHeader.match(/filename="?([^"]+)"?/); if (filenameMatch?.[1]) { filename = filenameMatch[1]; } } link.download = filename;
为什么GET请求能用?
当使用<Link>或直接在地址栏访问GET接口时,浏览器是直接导航到目标URL,会自动识别响应头里的Content-Disposition: attachment并触发下载流程;而fetch属于AJAX请求,是脚本发起的异步请求,浏览器不会自动处理下载逻辑,必须手动触发。
内容的提问来源于stack exchange,提问作者WindCheck
相关产品推荐
相关产品推荐

