vue-electron 批量生成 PDF

发布时间 2023-07-11 10:06:02作者: maze365

最近有个需求,需要批量下载 pdf,单份还好,但多份时会超时。
需要改成一份一份下载,先选择下载的存储路径,再自动下载到选择的目录中,一开始使用了 will-download,但在测试过程中,测服下载速度很慢,发现保存地址还是会弹出来,下载一次弹出一份。
因此打算试试利用 electron 原来的生成 pdf 功能

计划利用一个隐藏窗口来生成PDF,打开隐藏窗口后,加载数据,判断加载完成后,开始生成 PDF 页面,会涉及到 electron 的打开新窗口、选择文件夹、生成 PDF 三个功能

官方API

开发环境:electron4+

选择存储目录

// html
created: function() {
    // 监听方法一般放在 created 就行
    ipcRenderer.on('selected-directory', (event, path) => {
        this.fileSavePath = path
    })
}
// 调用
ipcRenderer.send('select-file-dialog')

beforeDestroy() {
    // 因为 .on 监听方法会一直存在,导致多次监听,所以每次退出页面把监听移除掉就行了
    ipcRenderer.removeAllListeners('selected-directory')
}
<!--main.js-->
const {ipcMain, dialog} = require('electron')
ipcMain.on('select-file-dialog', (event) => {
  dialog.showOpenDialog({
    title: '选择文件夹',
    buttonLabel: '确定',
    properties: ['openFile', 'openDirectory']
  }, (files) => {
    if (files) {
    // 将得到的路径传回页面存起来
      event.sender.send('selected-directory', files)
    }
  })
})

打开新窗口

主进程打开新窗口并跳到某个页面

let {href} = this.$router.resolve({
    name: urlName,
    query: { id: this.id, pdfPath: this.pdfPath}
});
ipcRenderer.send('open-window', `${href}`)

let sideWIndow
ipcMain.on('open-window', (event, _data) => {
// 判断下隐藏窗口是否存在,如果不存在才打开一个新窗口
  if (!sideWIndow) {
    sideWIndow = new BrowserWindow({
      width: 1280,
      height: 720,
      show: false // 是否隐藏窗口,在测试过程中,可以先改成 true 来看跳转的页面是否正确
    })
  }
  // 判断了下是否是开发环境
  let url = `file://${__dirname}/index.html${_data}`
  if (process.env.NODE_ENV === 'development') {
    url = `http://localhost:9080${_data}`
  }
  // 子窗口加载页面
  sideWIndow.loadURL(url)
  sideWIndow.on('closed', () => {
    sideWIndow = null
  })
})
// 关闭窗口的指令
ipcMain.on('close-window', (event, _data) => {
  if (sideWIndow) {
    sideWIndow.close()
  }
})

关闭窗口

// 退出此页面时,关闭窗口
beforeDestroy() {
    ipcRenderer.send('close-window')
}

// 主窗口有个关闭窗口事件,我们在这里也加个判断,把隐藏窗口一起关了
mainWindow.on('closed', () => {
    mainWindow = null
    if (sideWindow) {
      sideWindow.close()
    }
})

生成 pdf

// 这里生成报告页还是一份一份生成的,只要在前端遍历,有接收到生成成功的信号,就在下载下一份就可以了
// html
// 生成 PDF 需要一个存储路径,以及文件名
ipcRenderer.send('print-all-pdf', 'E:\name.pdf')
// 接收
ipcRenderer.on('wrote-all-pdf', (event, data) => {
    console.log('报告下载成功!')
})

<!--main.js-->
// 生成 PDF 放在同个页面新建窗口的同一个页面
// mainWindow 是主窗口,用来接收子窗口下载报告成功的指令
const fs = require('fs')
ipcMain.on('print-all-pdf', (event, _data) => {
  const pdfPath = _data
  sideWindow.webContents.printToPDF({}, (error, data) => {
    if (error) console.error(error)
    fs.writeFile(pdfPath, data, (error) => {
      if (error) {
        console.error(error)
      }
      if (error) {
        mainWindow.webContents.send('wrote-all-pdf-err', pdfPath)
      } else {
        mainWindow.webContents.send('wrote-all-pdf', pdfPath)
      }
    })
  })
})
ipcMain.on('print-err-pdf', (event, _data) => {
  mainWindow.webContents.send('wrote-all-pdf-err')
})

在下载成功的时候,可以触发事件去下载下一份报告