Angular调用Node服务获取S3 PDF文件显示空白问题排查
问题原因
你在Node服务里把S3返回的二进制PDF数据转成了UTF-8字符串,这会破坏PDF的二进制结构——UTF-8是文本编码,无法正确保留二进制文件的原始字节,传到前端后生成的Blob自然无效,所以打开后显示空白。
解决方案
1. 修改Node端代码,保留二进制数据
不要将S3返回的流转成UTF-8字符串,直接返回二进制Buffer或者将流直接pipe到HTTP响应:
方式一:返回Buffer(适合小文件)
替换原流处理函数和读取逻辑:
// 替换原streamToString为streamToBuffer,直接返回Buffer const streamToBuffer = (stream) => new Promise((resolve, reject) => { const chunks = []; stream.on("data", (chunk) => chunks.push(chunk)); stream.on("error", reject); stream.on("end", () => resolve(Buffer.concat(chunks))); }); const readFile = async function getObj(key) { const params = { Bucket: vBucket, Key: key, }; const command = new GetObjectCommand(params); const response = await client.send(command); return streamToBuffer(response.Body); }; // 假设用Express搭建接口,返回Buffer并设置正确的Content-Type app.get('/getfile', async (req, res) => { const key = req.query.key; try { const pdfBuffer = await readFile(key); res.set('Content-Type', 'application/pdf'); res.send(pdfBuffer); } catch (err) { res.status(500).json({ error: err.message }); } });
方式二:直接将S3流pipe到响应(适合大文件,更高效)
这种方式无需把整个文件加载到内存,直接将S3的输出流转发给前端:
const readFile = async function getObj(res, key) { const params = { Bucket: vBucket, Key: key, }; const command = new GetObjectCommand(params); const response = await client.send(command); res.set('Content-Type', 'application/pdf'); // 将S3的流直接pipe到HTTP响应 response.Body.pipe(res); }; // 接口处理逻辑 app.get('/getfile', async (req, res) => { const key = req.query.key; try { await readFile(res, key); } catch (err) { res.status(500).json({ error: err.message }); } });
2. 前端代码调整(可选)
如果后端直接返回二进制PDF,你当前的前端代码(使用arraybuffer或blob作为responseType)已经可以正常工作。也可以简化为:
// Angular服务部分 getObj(key: string): Observable<Blob>{ return this.http.get(environment.s3Ep + '/getfile?key=' + key, { responseType: 'blob' }); } // 调用部分 this.s3Svc.getObj(key).subscribe( res => { const fileURL = URL.createObjectURL(res); window.open(fileURL); } );
内容的提问来源于stack exchange,提问作者elesh.j
相关产品推荐
相关产品推荐

