如何将PDF从服务器直传至浏览器?解决AWS多EC2实例文件访问问题
解决方案
1. 直接流式传输PDF到浏览器(无需本地存储)
跳过本地文件写入步骤,直接将第三方返回的Base64格式PDF解码后作为HTTP响应发送给浏览器,彻底避免本地存储带来的跨实例问题。
修改后的代码示例(以Express路由为例):
app.get('/download-pdf/:id', async (req, res) => { try { const { id } = req.params; const pdfData = await someThirdParty(id); if (!pdfData.data.data.success) { throw new Error(pdfData.data.data.message); } // 移除Base64前缀并解码为Buffer const base64Pdf = pdfData.data.data.report.replace(/^data:application\/pdf;base64,/, ''); const pdfBuffer = Buffer.from(base64Pdf, 'base64'); // 设置响应头,告知浏览器这是可下载的PDF文件 res.setHeader('Content-Type', 'application/pdf'); res.setHeader('Content-Disposition', 'attachment; filename="report.pdf"'); res.setHeader('Content-Length', pdfBuffer.length); // 直接将Buffer发送给浏览器 res.send(pdfBuffer); } catch (err) { res.status(500).send(`下载失败: ${err.message}`); } });
如果第三方服务支持返回二进制流,可进一步优化为流式传输(避免全量加载到内存):
const axios = require('axios'); app.get('/download-pdf/:id', async (req, res) => { try { const { id } = req.params; // 配置请求直接获取二进制流 const response = await axios.get(`第三方服务PDF接口/${id}`, { responseType: 'stream' }); if (!response.data.success) { throw new Error(response.data.message); } // 设置响应头 res.setHeader('Content-Type', 'application/pdf'); res.setHeader('Content-Disposition', 'attachment; filename="report.pdf"'); // 将第三方返回的流直接管道到响应流 response.data.pipe(res); } catch (err) { res.status(500).send(`下载失败: ${err.message}`); } });
2. 无服务器化改造(替换EC2集群)
要构建无服务器高效系统,推荐用AWS Lambda + API Gateway替代EC2:
- 用Lambda函数处理PDF请求逻辑(复用上面的流式传输代码)
- 通过API Gateway暴露HTTP端点,用户直接请求该端点
- 无需维护EC2实例,也不用配置粘性会话,Lambda自动按需扩缩容
Lambda适配代码(Node.js运行时):
const axios = require('axios'); exports.handler = async (event) => { try { const id = event.pathParameters.id; const pdfData = await someThirdParty(id); if (!pdfData.data.data.success) { throw new Error(pdfData.data.data.message); } const base64Pdf = pdfData.data.data.report.replace(/^data:application\/pdf;base64,/, ''); return { statusCode: 200, headers: { 'Content-Type': 'application/pdf', 'Content-Disposition': 'attachment; filename="report.pdf"' }, body: base64Pdf, isBase64Encoded: true }; } catch (err) { return { statusCode: 500, body: JSON.stringify({ error: `下载失败: ${err.message}` }) }; } }; // 第三方服务请求封装 async function someThirdParty(id) { return axios.get(`第三方服务的PDF接口/${id}`); }
核心优势
- 彻底摆脱粘性会话依赖:每个请求独立处理,无需绑定特定实例
- 自动扩缩容:流量高峰时Lambda自动扩容,低峰时缩容,降低成本
- 零本地存储:数据全程在请求链路中传输,不落地任何服务器磁盘
内容的提问来源于stack exchange,提问作者Developer
相关产品推荐
相关产品推荐

