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

如何在Electron JS + Vue项目中实现PDF(如发票)的创建与保存功能

Electron + Vue 生成发票PDF 可行方案及避坑指南

你之前试用的第三方PDF库大多是面向纯Node.js环境设计的,在Electron环境下容易出现原生模块ABI不兼容、沙箱权限限制等报错问题,用Electron官方自带的webContents.printToPDF()是最稳妥的方案,完全可以满足发票类PDF的格式定制需求。

优先推荐:使用Electron原生API实现(无额外依赖、适配性最高)

实现步骤

  • 首先在Vue项目中单独开发发票模板页面,把发票的样式、排版用HTML+CSS写好,支持动态填充用户、金额等发票数据,也可以用CSS的page-break-after: always属性控制分页位置,避免内容被截断。
  • 渲染进程通过IPC通信向主进程发送生成PDF的请求,传递发票的动态数据。
    渲染进程示例代码:
    // 渲染进程(Vue页面)发送请求
    const generatePdf = async (invoiceData) => {
      const savePath = await window.ipcRenderer.invoke('generate-invoice-pdf', invoiceData)
      console.log('PDF已保存至:', savePath)
    }
    
  • 主进程接收请求后,新开隐藏窗口加载填好数据的发票模板页面,调用原生API生成PDF后保存到本地。
    主进程示例代码:
    const { ipcMain, BrowserWindow, dialog } = require('electron')
    const fs = require('fs/promises')
    
    ipcMain.handle('generate-invoice-pdf', async (event, invoiceData) => {
      // 新建隐藏窗口用于渲染发票内容
      const printWin = new BrowserWindow({
        show: false,
        webPreferences: {
          contextIsolation: true,
          nodeIntegration: false
        }
      })
    
      // 加载发票模板页面,开发环境用localhost地址,打包后用本地app协议路径
      const templateUrl = process.env.NODE_ENV === 'development' 
        ? `http://localhost:5173/invoice?data=${encodeURIComponent(JSON.stringify(invoiceData))}`
        : `app://./invoice.html?data=${encodeURIComponent(JSON.stringify(invoiceData))}`
      await printWin.loadURL(templateUrl)
    
      // 生成PDF配置,可自定义纸张大小、边距、是否打印背景等
      const pdfBuffer = await printWin.webContents.printToPDF({
        pageSize: 'A4',
        margins: {
          top: 1.5,
          bottom: 1,
          left: 0.8,
          right: 0.8
        },
        printBackground: true, // 必须开启,否则自定义背景色、边框样式会丢失
        headerFooter: {
          pageNumber: true // 可自定义页眉页脚,比如加发票编号等
        }
      })
    
      // 弹出保存对话框让用户选择存储路径
      const { filePath, canceled } = await dialog.showSaveDialog({
        defaultPath: `发票_${Date.now()}.pdf`,
        filters: [{ name: 'PDF文件', extensions: ['pdf'] }]
      })
    
      if (!canceled && filePath) {
        await fs.writeFile(filePath, pdfBuffer)
      }
      printWin.destroy()
      return filePath
    })
    

第三方库报错解决方法

如果你坚持要使用PdfKit、pdf-creator-node这类第三方库,需要处理Electron和纯Node环境的兼容性问题:

  • 所有第三方PDF库的调用逻辑都放在主进程执行,不要在渲染进程调用,避免沙箱权限限制。
  • 安装依赖后执行electron-rebuild命令,重建适配当前Electron版本的原生模块,解决ABI不一致导致的加载报错。
  • 在electron-builder的配置文件中,把用到的PDF依赖添加到externals列表中,打包时会单独处理原生模块,避免打包后丢失依赖。

通用避坑点

  • 发票样式调试时可以先把隐藏窗口的show属性设为true,确认页面渲染正常后再改成隐藏。
  • 打包时要确保发票模板页面被正确打包到应用资源目录中,不要使用开发环境的本地服务器地址,否则打包后页面无法加载。
  • 不要为了适配第三方库随意开启nodeIntegration、关闭contextIsolation,会带来严重的安全风险。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.29 04:24:02