如何通过Next.js API路由下载第三方PDF且避免暴露客户端API密钥
问题核心原因
- 服务端API路由错误地将PDF二进制流包裹在JSON对象中返回,实际返回的是JSON文本而非PDF二进制内容
- 服务端未正确处理第三方接口返回的Response对象,直接把Response实例当作数据返回
- 客户端fetch配置使用了Node.js专属参数,浏览器环境不生效
修改方案
1. 修改 /api/getPDFFile.js 代码
const options = { method: 'GET', headers: { 'Subscription-Key': process.env.GUIDE_STAR_CHARITY_CHECK_API_PDF_KEY, }, rejectUnauthorized: false, }; const pdfResponse = await fetch( 'https://apidata.guidestar.org/charitycheckpdf/v1/pdf/26-4775012', options ); // 校验第三方接口返回状态 if (!pdfResponse.ok) { return res.status(pdfResponse.status).send('Failed to get PDF from third party'); } // 将第三方返回的流转成Buffer const pdfBuffer = await pdfResponse.arrayBuffer(); // 设置正确的响应头,直接返回二进制内容 res.setHeader('Content-Type', 'application/pdf'); res.setHeader('Content-Disposition', 'attachment; filename="test.pdf"'); return res.status(200).send(Buffer.from(pdfBuffer));
2. 修改客户端 pages/getPDF.js 代码
<button type="button" onClick={async () => { try { const response = await fetch('/api/guidestar/charitycheckpdf', { method: 'GET', }); if (!response.ok) { throw new Error('Sorry, I could not find that file.'); } const blob = await response.blob(); const url = window.URL.createObjectURL(blob); const a = document.createElement('a'); a.style.display = 'none'; a.href = url; a.download = 'test.pdf'; document.body.appendChild(a); a.click(); window.URL.revokeObjectURL(url); document.body.removeChild(a); } catch (err) { console.error(err); alert(err.message); } }}>Click to Download</button>
修改完成后即可正常下载打开PDF文件。
内容的提问来源于stack exchange,提问作者JoshJoe
相关产品推荐
相关产品推荐

