Electron打印功能:网页内容打印与PDF生成

Electron打印功能:网页内容打印与PDF生成

【免费下载链接】electron 使用Electron构建跨平台桌面应用程序,支持JavaScript、HTML和CSS 【免费下载链接】electron 项目地址: https://gitcode.com/GitHub_Trending/el/electron

还在为Electron应用的打印功能头疼吗?本文将为你全面解析Electron的打印API,从基础打印到高级PDF生成,助你轻松实现专业级打印功能!

概述

Electron提供了强大的打印功能,允许开发者通过webContents模块实现网页内容的物理打印和PDF文件生成。无论是简单的文档打印还是复杂的报表导出,Electron都能满足你的需求。

核心API概览

Electron的打印功能主要通过以下两个核心方法实现:

方法描述返回值
webContents.print([options], [callback])打印网页内容到物理打印机无/Promise
webContents.printToPDF(options)将网页内容导出为PDF文件Promise

基础打印功能

1. 简单打印

最基本的打印功能只需要调用print()方法:

const { BrowserWindow } = require('electron')

// 创建窗口
const win = new BrowserWindow({ width: 800, height: 600 })
win.loadURL('https://example.com')

// 打印当前页面
win.webContents.print()

2. 带配置的打印

const printOptions = {
  silent: false,           // 是否显示打印对话框
  printBackground: true,   // 是否打印背景
  color: true,            // 彩色打印
  marginType: 0,          // 边距类型:0-默认,1-无,2-可打印区域
  landscape: false,       // 横向打印
  pagesPerSheet: 1,       // 每张纸打印页数
  copies: 1,              // 打印份数
  deviceName: ''          // 打印机设备名
}

win.webContents.print(printOptions, (success, failureReason) => {
  if (success) {
    console.log('打印成功')
  } else {
    console.error('打印失败:', failureReason)
  }
})

PDF生成功能

1. 基础PDF导出

const fs = require('fs').promises

async function exportToPDF() {
  try {
    const data = await win.webContents.printToPDF({})
    await fs.writeFile('output.pdf', data)
    console.log('PDF导出成功')
  } catch (error) {
    console.error('PDF导出失败:', error)
  }
}

// 调用导出函数
exportToPDF()

2. 高级PDF配置

const pdfOptions = {
  printBackground: true,      // 打印背景
  landscape: false,           // 横向布局
  pageSize: 'A4',            // 页面尺寸:A3, A4, A5, Legal, Letter, Tabloid
  marginsType: 0,            // 边距类型
  scale: 1.0,                // 缩放比例
  headerTemplate: `
    <div style="font-size:10px;text-align:center;width:100%;">
      <span class="title"></span>
      <span class="date"></span>
      <span class="url"></span>
      <span class="pageNumber"></span>
      <span class="totalPages"></span>
    </div>
  `,
  footerTemplate: `
    <div style="font-size:8px;text-align:center;width:100%;">
      第 <span class="pageNumber"></span> 页 / 共 <span class="totalPages"></span> 页
    </div>
  `,
  pageRanges: '1-5'          // 页面范围
}

win.webContents.printToPDF(pdfOptions)
  .then(data => fs.writeFile('document.pdf', data))
  .catch(error => console.error('PDF生成错误:', error))

打印机管理

获取打印机列表

async function getPrinters() {
  try {
    const printers = await win.webContents.getPrintersAsync()
    console.log('可用打印机:', printers)
    
    printers.forEach(printer => {
      console.log(`打印机: ${printer.name}`)
      console.log(`描述: ${printer.description}`)
      console.log(`状态: ${printer.status}`)
      console.log(`是否默认: ${printer.isDefault}`)
      console.log('---')
    })
  } catch (error) {
    console.error('获取打印机列表失败:', error)
  }
}

实战案例:完整的打印管理器

const { app, BrowserWindow, ipcMain, dialog } = require('electron')
const fs = require('fs').promises
const path = require('path')

class PrintManager {
  constructor(mainWindow) {
    this.mainWindow = mainWindow
    this.setupIPCHandlers()
  }

  setupIPCHandlers() {
    // 处理打印请求
    ipcMain.handle('print-document', async (event, options) => {
      return await this.printDocument(options)
    })

    // 处理PDF导出请求
    ipcMain.handle('export-pdf', async (event, options, filePath) => {
      return await this.exportToPDF(options, filePath)
    })

    // 获取打印机列表
    ipcMain.handle('get-printers', async () => {
      return await this.getPrinters()
    })
  }

  async printDocument(options = {}) {
    return new Promise((resolve, reject) => {
      this.mainWindow.webContents.print({
        silent: options.silent || false,
        printBackground: options.printBackground || true,
        color: options.color || true,
        marginType: options.marginType || 0,
        deviceName: options.deviceName || '',
        ...options
      }, (success, failureReason) => {
        if (success) {
          resolve({ success: true })
        } else {
          reject({ success: false, reason: failureReason })
        }
      })
    })
  }

  async exportToPDF(options = {}, filePath) {
    try {
      const data = await this.mainWindow.webContents.printToPDF({
        printBackground: true,
        landscape: false,
        pageSize: 'A4',
        marginsType: 1,
        ...options
      })

      if (filePath) {
        await fs.writeFile(filePath, data)
        return { success: true, path: filePath }
      } else {
        return { success: true, data: data.toString('base64') }
      }
    } catch (error) {
      return { success: false, error: error.message }
    }
  }

  async getPrinters() {
    try {
      const printers = await this.mainWindow.webContents.getPrintersAsync()
      return printers.map(printer => ({
        name: printer.name,
        description: printer.description,
        status: printer.status,
        isDefault: printer.isDefault
      }))
    } catch (error) {
      throw new Error(`获取打印机失败: ${error.message}`)
    }
  }
}

// 在渲染进程中使用
/*
// 渲染进程代码
const { ipcRenderer } = require('electron')

// 打印文档
async function printDocument() {
  try {
    const result = await ipcRenderer.invoke('print-document', {
      silent: true,
      printBackground: true
    })
    console.log('打印结果:', result)
  } catch (error) {
    console.error('打印错误:', error)
  }
}

// 导出PDF
async function exportPDF() {
  try {
    const result = await ipcRenderer.invoke('export-pdf', {}, 'document.pdf')
    console.log('PDF导出结果:', result)
  } catch (error) {
    console.error('PDF导出错误:', error)
  }
}

// 获取打印机列表
async function loadPrinters() {
  try {
    const printers = await ipcRenderer.invoke('get-printers')
    console.log('打印机列表:', printers)
  } catch (error) {
    console.error('获取打印机错误:', error)
  }
}
*/

打印样式优化

为了获得更好的打印效果,需要在CSS中添加打印样式:

/* 打印样式 */
@media print {
  /* 隐藏不需要打印的元素 */
  .no-print {
    display: none !important;
  }
  
  /* 确保背景颜色打印 */
  * {
    -webkit-print-color-adjust: exact !important;
    print-color-adjust: exact !important;
  }
  
  /* 分页控制 */
  .page-break {
    page-break-after: always;
  }
  
  /* 优化文本渲染 */
  body {
    font-size: 12pt;
    line-height: 1.5;
  }
  
  /* 确保链接可读 */
  a {
    color: #000 !important;
    text-decoration: underline !important;
  }
  
  /* 打印边距 */
  @page {
    margin: 1cm;
  }
  
  @page :first {
    margin: 2cm 1cm 1cm 1cm;
  }
}

常见问题与解决方案

问题1:打印对话框不显示

解决方案:确保silent选项设置为false

win.webContents.print({ silent: false })

问题2:背景颜色不打印

解决方案:设置printBackground: true并确保CSS正确

win.webContents.print({ printBackground: true })

问题3:PDF文件损坏

解决方案:使用正确的Buffer处理

win.webContents.printToPDF({})
  .then(data => {
    // 确保使用Buffer正确写入
    fs.writeFileSync('output.pdf', Buffer.from(data))
  })

问题4:跨域内容打印问题

解决方案:确保所有资源都是同源或已正确加载

// 等待所有资源加载完成
win.webContents.on('did-finish-load', () => {
  // 此时进行打印操作
  win.webContents.print()
})

性能优化建议

  1. 延迟打印:等待页面完全加载后再执行打印操作
  2. 内存管理:大量PDF生成时注意内存使用
  3. 错误处理:添加完善的错误处理和重试机制
  4. 进度反馈:为用户提供打印进度反馈
// 带进度反馈的打印函数
async function printWithProgress(options) {
  showProgress('准备打印...')
  
  try {
    // 等待页面加载完成
    await new Promise(resolve => {
      if (win.webContents.isLoading()) {
        win.webContents.once('did-finish-load', resolve)
      } else {
        resolve()
      }
    })
    
    showProgress('正在打印...')
    const result = await printDocument(options)
    showProgress('打印完成', 'success')
    return result
    
  } catch (error) {
    showProgress('打印失败', 'error')
    throw error
  }
}

总结

Electron的打印功能强大而灵活,通过webContents.print()webContents.printToPDF()两个核心方法,开发者可以轻松实现从简单打印到复杂PDF导出的各种需求。关键要点包括:

  • ✅ 掌握基础打印和PDF导出API
  • ✅ 理解各种打印选项的作用
  • ✅ 实现完善的错误处理和用户反馈
  • ✅ 优化打印样式和页面布局
  • ✅ 管理打印机设备和打印任务

通过本文的详细讲解和代码示例,相信你已经能够熟练使用Electron的打印功能,为你的桌面应用添加专业的打印能力!

立即尝试:在你的Electron项目中实现这些打印功能,提升用户体验和应用价值!

【免费下载链接】electron 使用Electron构建跨平台桌面应用程序,支持JavaScript、HTML和CSS 【免费下载链接】electron 项目地址: https://gitcode.com/GitHub_Trending/el/electron

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值