You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Node.js NestJS封装第三方API下载PDF黑屏问题求助

解决NestJS封装PDF API后下载黑屏的问题

问题根源分析

  1. 错误的响应头设置:响应中添加了Accept头,这是请求头字段,用于客户端告知服务器接受的内容类型,响应里无需设置该字段。
  2. 二进制数据处理不当:原代码手动创建Readable流的方式存在隐患,Node.js环境下Axios的responseType: "blob"会返回Buffer,但手动推送流的逻辑可能导致数据损坏。
  3. 冗余请求头: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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.13 17:43:36