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

NestJS使用jsPDF生成带图PDF:响应返回无图片的正确处理方法

解决NestJS中jsPDF生成PDF返回客户端无图片的问题

你的问题核心在于返回客户端时的PDF数据编码处理错误:doc.output()默认返回UTF-8编码的字符串,直接推送到Readable流会导致图片的二进制数据被破坏;而本地保存时你指定了'binary'编码,所以能正常显示图片。另外代码里还有个笔误:writeFileSync里的data应该是pdf,不过这是本地保存的问题,和客户端返回无关。

下面是几种正确的响应实现方式:

方法一:直接返回Buffer(最简单)

利用doc.output('arraybuffer')获取二进制数据,转换成Buffer后直接通过Response发送:

@Post('/')
async generatePdf(@Res() response: Response) {
  const doc = new jsPDF();

  doc.text('PDF with image', 10, 10);
  const imageData = readFileSync('src/pdf/template_1.png');
  doc.addImage(imageData, 'PNG', 0, 0, 100, 100);
  
  // 获取PDF的ArrayBuffer格式数据,转成Buffer
  const pdfBuffer = Buffer.from(doc.output('arraybuffer'));

  // 设置响应头
  response.set({
    'Content-Type': 'application/pdf',
    'Content-Disposition': 'inline; filename="document.pdf"' // 可选,指定文件名,改成attachment可触发下载
  });

  // 直接发送Buffer
  response.send(pdfBuffer);
}

方法二:正确处理Readable流

如果一定要用流,需确保推送的是二进制数据而非字符串:

@Post('/')
async generatePdf(@Res() response: Response) {
  const doc = new jsPDF();

  doc.text('PDF with image', 10, 10);
  const imageData = readFileSync('src/pdf/template_1.png');
  doc.addImage(imageData, 'PNG', 0, 0, 100, 100);
  
  // 获取ArrayBuffer并转成Buffer
  const pdfBuffer = Buffer.from(doc.output('arraybuffer'));
  const stream = new Readable();

  stream.push(pdfBuffer);
  stream.push(null);

  response.set({
    'Content-Type': 'application/pdf',
    'Content-Disposition': 'inline; filename="document.pdf"'
  });

  stream.pipe(response);
}

方法三:使用NestJS的StreamableFile(推荐)

NestJS提供的StreamableFile工具类能更优雅地处理文件流响应,无需手动管理流:

import { StreamableFile } from '@nestjs/common';
import { createReadStream } from 'fs';

@Post('/')
async generatePdf() {
  const doc = new jsPDF();

  doc.text('PDF with image', 10, 10);
  const imageData = readFileSync('src/pdf/template_1.png');
  doc.addImage(imageData, 'PNG', 0, 0, 100, 100);
  
  // 先将PDF写入临时文件(你已能正常保存)
  const tempPath = '/tmp/document.pdf';
  writeFileSync(tempPath, doc.output('arraybuffer'));

  // 创建可读流并包装成StreamableFile
  const fileStream = createReadStream(tempPath);
  return new StreamableFile(fileStream, {
    type: 'application/pdf',
    disposition: 'inline; filename="document.pdf"'
  });
}

关键说明

  • 必须使用doc.output('arraybuffer')获取二进制格式的PDF数据,避免字符串编码导致的图片损坏;
  • Content-Disposition响应头可控制浏览器是直接预览PDF(inline)还是触发下载(attachment);
  • 使用StreamableFile时无需手动注入@Res(),NestJS会自动处理响应头和流的传输逻辑。

内容的提问来源于stack exchange,提问作者Ivan

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.19 10:43:33