Node.js NestJS封装第三方API下载PDF黑屏问题求助
解决NestJS封装PDF API后下载黑屏的问题
问题根源分析
- 错误的响应头设置:响应中添加了
Accept头,这是请求头字段,用于客户端告知服务器接受的内容类型,响应里无需设置该字段。 - 二进制数据处理不当:原代码手动创建
Readable流的方式存在隐患,Node.js环境下Axios的responseType: "blob"会返回Buffer,但手动推送流的逻辑可能导致数据损坏。 - 冗余请求头:GET请求通常不需要设置
Content-Type头,除非第三方API明确要求,多余的头字段可能干扰响应解析。
修正方案
方案1:直接返回二进制Buffer(推荐)
服务层代码修改
async getLabelPdf(refId: string): Promise<AxiosResponse> { const url = `your_actual_third_party_url`; const headers = { "x-api-key": "my_key", "Accept": "application/pdf" // 仅保留必要请求头 }; // Node.js环境下用arraybuffer获取正确二进制数据 return axios.get(url, { headers, responseType: "arraybuffer" }); }
控制器代码修改
import { Response } from 'express'; import { Get, Res } from '@nestjs/common'; @Get("generate") async generate(@Res() res: Response): Promise<void> { try { // 传入实际的refId参数 const pdfResponse = await this.myService.getLabelPdf('your_ref_id'); // 设置正确响应头 res.setHeader('Content-Type', 'application/pdf'); // 可选:inline为浏览器预览,attachment触发下载 res.setHeader('Content-Disposition', 'inline; filename="generated.pdf"'); // 直接发送Buffer数据,无需手动创建流 res.send(pdfResponse.data); } catch (error) { res.status(500).send('生成PDF失败'); } }
方案2:流式传输(适合大文件)
如果PDF文件较大,推荐直接流式传输以降低内存占用:
服务层代码修改
async getLabelPdf(refId: string): Promise<AxiosResponse> { const url = `your_actual_third_party_url`; const headers = { "x-api-key": "my_key", "Accept": "application/pdf" }; // 设置responseType为stream,直接获取响应流 return axios.get(url, { headers, responseType: "stream" }); }
控制器代码修改
import { Response } from 'express'; import { Get, Res } from '@nestjs/common'; @Get("generate") async generate(@Res() res: Response): Promise<void> { try { const pdfResponse = await this.myService.getLabelPdf('your_ref_id'); res.setHeader('Content-Type', 'application/pdf'); res.setHeader('Content-Disposition', 'inline; filename="generated.pdf"'); // 将第三方API的响应流直接pipe到客户端响应 pdfResponse.data.pipe(res); } catch (error) { res.status(500).send('生成PDF失败'); } }
额外注意事项
- 修正控制器与服务层的方法调用匹配问题:原代码中控制器调用
generate(),但服务层方法是getLabelPdf(),需确保参数和方法名对应。 - 可对比直接调用第三方API和封装后API返回的二进制数据MD5值,验证数据是否在传输过程中损坏。
内容的提问来源于stack exchange,提问作者Code Guru
相关产品推荐
相关产品推荐

