使用fetch方法搭配NodeJS路由时PDF无法加载的问题
问题解决:Node.js直接返回PDF流而非存储文件的正确实现
核心问题分析
你的代码存在两个关键错误,导致直接pipe PDF流无法正常工作:
- 后端逻辑冲突:在将PDF流pipe到response后,又调用了
response.send(JSON.stringify(...)),这会在PDF数据后追加JSON内容,彻底破坏PDF格式;同时响应头已设置为application/pdf,返回JSON完全不符合协议规范。 - 前端解析错误:当前代码默认将响应解析为JSON,但后端返回PDF流时,前端需要接收Blob类型数据并处理,而非尝试解析JSON。
修正后的后端代码
移除多余的response.send()调用,确保只返回纯净的PDF流:
function _postMultiplePrint(request, response) { var fonts = { Roboto: { normal: 'public/fonts/OpenSans-Regular.ttf', bold: 'public/fonts/OpenSans-Bold.ttf', italics: 'public/fonts/OpenSans-Italic.ttf', bolditalics: 'public/fonts/OpenSans-BoldItalic.ttf' } }, printer = new PdfPrinter(fonts), docDefinition, pdfDoc; docDefinition = { content: [ { text: 'This paragraph fills full width, as th' } ], pageSize: 'A4', pageMargins: [72, 72], footer: {}, background: {} }; pdfDoc = printer.createPdfKitDocument(docDefinition); response.setHeader('Content-type', 'application/pdf'); response.setHeader('Content-disposition', 'inline; filename="book.pdf"'); // 监听PDF流结束事件,自动结束响应 pdfDoc.on('end', () => response.end()); pdfDoc.pipe(response); pdfDoc.end(); }
修正后的前端代码
修改fetch处理逻辑,接收Blob并在页面中打开PDF:
fetch(url, { method: 'POST', headers: { 'Content-Type': 'application/json' }, credentials: 'same-origin', body: JSON.stringify({ ids: arrayIds }) }).then(function(response) { if (!response.ok) throw new Error('请求失败'); return response.blob(); }).then(function(blob) { // 创建临时URL并在当前页面打开PDF const pdfUrl = URL.createObjectURL(blob); document.location.href = pdfUrl; // 可选:若在新标签页打开,可替换为下面一行,之后记得释放临时URL // window.open(pdfUrl, '_blank'); // setTimeout(() => URL.revokeObjectURL(pdfUrl), 10000); }).catch(function(error) { console.error('生成PDF失败:', error); });
兼容原有reload逻辑的进阶处理
如果需要保留原有的页面刷新逻辑,可以在前端先判断响应类型,分别处理JSON和PDF流:
fetch(url, { /* 原有配置 */ }) .then(response => { const contentType = response.headers.get('Content-Type'); if (contentType.includes('application/json')) { return response.json(); } else if (contentType.includes('application/pdf')) { return response.blob(); } throw new Error('未知响应类型'); }) .then(data => { if (typeof data === 'object' && data.reload) { document.location.reload(); } else if (data instanceof Blob) { const pdfUrl = URL.createObjectURL(data); document.location.href = pdfUrl; } })
内容的提问来源于stack exchange,提问作者tonymx227
相关产品推荐
相关产品推荐

