最近接到的需求中有在electron中实现打印pdf文件的功能。从网上找了很多第三方工具,基本上是在页面中打开pdf,然后打印web页面。这固然可以实现打印功能,但是打印的实际上只是个web页面,而非真正的pdf源文件。
该方法实际上是通过node执行命令来调用SumatraPDF从而打印pdf文件,所以我们需要把SumatraPDF目录直接放在项目static(vue-cli3为public)目录下
完整需求为通过接口获取pdf文件流,打印pdf。(这里只讲了打印pdf部分)
完整思路如下:
1.渲染进程调接口获取pdf文件流
import QS from 'qs'
const download = (url, query, cb, type) => {
var xhr = new XMLHttpRequest()
xhr.open(
"GET",
`${axios.defaults.baseURL}${url}?${QS.stringify(query)}`,
true
)
xhr.responseType = "blob"
xhr.setRequestHeader("Access-Token", sessionStorage.getItem("token"))
xhr.onload = function() {
if (this.status == 200) {
var blob = new Blob([this.response], {
type: "application/pdf;charset=utf-8",
})
//生成URL
let href = window.URL.createObjectURL(blob)
if (cb) {
// 有回调,根据type在回调中传入blob对象或url
if (type == "blob") {
cb(blob)
} else {
cb(href)
}
} else {
// 无回调,直接导出下载
let link = document.createElement("a")
link.download = "波形.pdf"
link.href = href
link.click()
}
}
}
xhr.send()
}
const printReport = (p, cb, type = "url") => download(`report/worklist/print`, p, cb, type)
2.将pdf文件流转为Buffer格式(先转为blob对象,然后通过FileReader转为Buffer)
exportReport(
{},
(blob) => {
let self = this
let reader = new FileReader()
reader.readAsDataURL(blob)
reader.addEventListener('loadend', () => {
// 通知主进程打印
ipc.send('printPDF', {
baseCode: Buffer.from(reader.result.split('base64,')[1], 'base64'),
})
})
},
'blob'
)
3.渲染进程与主进程通信,发送Buffer到主进程。主进程通过fs模块将pdf保存到本地,通过child_process执行SumatraPDF打印命令,完成打印
const cp = require('child_process');
const path = require("path");
const fs = require('fs');
const { app, ipcMain: ipc } = require("electron");
ipc.on('printPDF', (e, arg) => {
const writeFile = () => {
fs.writeFile('./data/waveform.pdf', arg.baseCode, { encoding: 'utf8' }, err => {
// 失败
if (err) {
// 向渲染进程发送消息通知失败
e.reply('defeatedDialog', err)
} else {
let pdfUrl = path.join(app.getAppPath(), process.env.NODE_ENV === 'development' ? '../data/waveform.pdf' : '../../data/waveform.pdf')
switch (process.platform) {
case 'darwin':
case 'linux':
cp.exec(
`SumatraPDF.exe -print-to-default "${pdfUrl}"`,
{
windowsHide: true,
cwd: path.join(app.getAppPath(), process.env.NODE_ENV === 'development' ? '../static/SumatraPDF' : './app/static/SumatraPDF'),
},
e => {
if (e) {
throw e
}
}
)
break
case 'win32':
cp.exec(
`SumatraPDF.exe -print-to-default "${pdfUrl}"`,
{
windowsHide: true,
cwd: path.join(app.getAppPath(), process.env.NODE_ENV === 'development' ? '../static/SumatraPDF' : './app/static/SumatraPDF'),
},
e => {
fs.unlink(pdfUrl, e => {})
if (e) {
throw e
}
}
)
break
default:
throw new Error('Platform not supported.')
}
}
})
}
if (fs.existsSync('./data')) {
writeFile()
} else {
fs.mkdir('./data', { recursive: true }, err => {
if (err) {
throw err
} else {
writeFile()
}
})
}
})
代码给大家贴出来了,有问题或有改进建议的小伙伴可以留言,我看到后会回复大家
附SumatraPDF文档:https://www.sumatrapdfreader.org/docs/Command-line-arguments.html