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

Node+Vue项目中用pdfkit生成PDF,blob-stream报Blob构造函数错误求助

解决方案:Node服务端生成PDF并实现邮件发送+客户端预览

问题根源

blob-stream 是为浏览器环境设计的工具,Node.js 运行时没有内置 Blob 构造函数,直接使用会抛出你遇到的「Blob is not a constructor/function」错误。我们需要改用 Node.js 原生的流处理方案,同时满足邮件发送和客户端预览两个需求。

实现步骤与代码修改

  1. 用 Node 原生流捕获PDF输出:使用 PassThrough 流收集pdfkit的输出,转为Buffer(Buffer是Node端处理二进制数据的标准方式)。
  2. 复用Buffer实现双需求:同一个Buffer既可以作为邮件附件发送,也能返回给客户端用于预览。
  3. 客户端设置响应类型:前端请求时指定responseType: 'blob',才能正确解析服务端返回的二进制PDF数据。

修改后的服务端代码

const pdfkit = require('pdfkit');
const nodemailer = require('nodemailer');
const { PassThrough } = require('stream');

// 完善邮件发送函数,新增PDF Buffer参数
async function sendMailer(email, pdfBuffer) {
  // 这里替换成你的邮件服务配置(比如QQ/163/Gmail的SMTP信息)
  const transporter = nodemailer.createTransport({
    host: 'smtp.example.com',
    port: 587,
    secure: false,
    auth: {
      user: 'your-email@example.com',
      pass: 'your-email-password'
    }
  });

  await transporter.sendMail({
    from: 'your-email@example.com',
    to: email,
    subject: '生成的PDF文档',
    text: '附件是你请求的PDF文件',
    attachments: [
      {
        filename: 'document.pdf',
        content: pdfBuffer,
        contentType: 'application/pdf'
      }
    ]
  });
}

app.post('/', async (req, res) => {
  try {
    const doc = new pdfkit();
    const passThroughStream = new PassThrough();
    const pdfChunks = [];

    // 收集PDF流的二进制片段
    passThroughStream.on('data', (chunk) => pdfChunks.push(chunk));
    passThroughStream.on('end', async () => {
      const pdfBuffer = Buffer.concat(pdfChunks);
      
      // 先发送邮件
      await sendMailer(req.body.email, pdfBuffer);
      
      // 再返回PDF给客户端,支持浏览器直接预览
      res.setHeader('Content-Type', 'application/pdf');
      // 用inline表示浏览器预览,改成attachment则触发下载
      res.setHeader('Content-Disposition', 'inline; filename="document.pdf"');
      res.send(pdfBuffer);
    });

    // 写入PDF内容
    doc.text('hallo!!!!', { fontSize: 50 });
    doc.pipe(passThroughStream);
    doc.end();
  } catch (err) {
    console.error(err);
    res.status(500).send('PDF生成或发送失败');
  }
});

Vue客户端预览代码示例

// 以axios为例,发送请求并预览PDF
async function getAndPreviewPDF(userEmail) {
  try {
    const response = await axios.post('/', { email: userEmail }, {
      responseType: 'blob' // 必须指定,否则会解析成乱码
    });
    
    // 创建Blob URL并打开预览
    const blobUrl = URL.createObjectURL(response.data);
    window.open(blobUrl);
    
    // 可选:如果要在页面内嵌入预览,用iframe
    // const iframe = document.createElement('iframe');
    // iframe.style.width = '100%';
    // iframe.style.height = '800px';
    // iframe.src = blobUrl;
    // document.querySelector('.pdf-preview-container').appendChild(iframe);
  } catch (error) {
    console.error('请求PDF失败:', error);
  }
}

关键注意事项

  • 邮件服务配置需要替换成你实际的SMTP信息,不同邮箱的SMTP地址/端口可能不同。
  • 服务端返回时的Content-Disposition头:inline让浏览器直接预览,attachment则触发下载,可根据需求切换。
  • 客户端必须设置responseType: 'blob',否则axios会把二进制PDF数据当成字符串解析,导致预览失败。

内容的提问来源于stack exchange,提问作者שמעון פוקס

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.26 05:48:22