使用electron导出pdf并预览
在开发过程中难免会遇到许多文档的输出,本文主要讲使用electron导出pdf的功能,原理就是将html代码转换为pdf文件:先使用showOpenDialogSync获取到保存文件的路径,获取到html(html样式尽量使用行内样式,不然容易出bug)后将文件路径和html通过electron的ipcRenderer.send发送到主进程,主进程接受到子进程发送的数据之后使用printToPDF
前言
在开发过程中难免会遇到许多文档的输出,本文主要讲使用electron导出pdf的功能,原理就是将html代码转换为pdf文件:先使用
showOpenDialogSync获取到保存文件的路径,获取到html(html样式尽量使用行内样式,不然容易出bug)后将文件路径和html通过electron的ipcRenderer.send发送到主进程,主进程接受到子进程发送的数据之后使用printToPDF将html代码转换为pdf文件,最后使用fs.writeFile将文件保存。
一、子进程
1.引入remote和ipcRenderer两个模块。
这个需要根据自己的项目引入具体的模块,作者已经引入
2.获取html代码
代码如下:
// 获取报告的html代码
getExportReportHtml(): string {
return `
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta name="author" content="CEditor">
<title>导出报告</title>
</head>
<body class="markdown-body code-github">
<h1>41312</h1>
</body>
</html>
`;
}
3.获取文件下载路径
代码如下:
let filePath = this.es.remote.dialog.showOpenDialogSync({
title: "导出报告",
buttonLabel: "导出报告",
properties: ["openDirectory"], //openDirectory选择文件夹
});
4.将html和文件下载路径发送到主进程
ipcRenderer的第一个参数做序列化处理,内容什么都可以,代码如下:
this.es.ipcRenderer.send(
"export-pdf",
(<string>"4a3s2f", { filePath, html, mode })
);
5.监听主进程反馈的信息
代码如下:
this.es.ipcRenderer.once("export-pdf-res", (_e, data) => {
console.log("结果:", data);
if (!data.success) {
this.message.error(data.msg);
}
});
二、主进程
1.显示pdf(预览)
参数比较多,解释都放在代码中注释了,代码如下:
let pdfWindow:any = new BrowserWindow({
webPreferences: {
nodeIntegration: true,//是否启用Node integration
webSecurity: false,//当设置为 false, 它将禁用同源策略
enableRemoteModule: true
},
show: obj.mode==1?true:false, // 是否显示窗口
width: 1000,
height: 800,
fullscreenable: true,//决定最大化/缩放窗口按钮是切换全屏模式还是最大化窗口
minimizable: false,//设置用户是否可以手动将窗口最小化。 在Linux上不起作用
modal:true,//是否为模态框
center:true,//是否居中显示
icon:'./src/assets/icons/icon.ico',//窗口的图标
// icon:'.\\icon.ico',
});
pdfWindow.loadURL(`data:text/html;charset=utf-8,${encodeURI(obj.html)}`);
2.下载pdf(预览)
下载pdf并通知子进程是否下载成功,代码如下:
pdfWindow.webContents.on('did-finish-load', () => {
// Use default printing options
const pdfPath = obj.filePath;
pdfWindow.webContents.printToPDF({
printBackground: true
}).then(data => {
fs.writeFile(pdfPath, data, error => {
if (error) throw error;
win.webContents.send('export-pdf-res', { success: true,msg:`导出成功,路径:${pdfPath}` });
pdfWindow.close();// 保存pdf过后关闭该窗口
pdfWindow = null;
});
}).catch(error => {
win.webContents.send('export-pdf-res', { success:false,msg: `导出失败,路径:${JSON.stringify(error)}` });
});
});
三、完整代码
1.子进程:
// 导出报告
/**
* @params mode 1:预览,2:导出
*/
exportReport(mode = 1) {
if (!this.es.remote) return;
let res = undefined;
let filePath = undefined;
if (mode == 2) {
res = this.es.remote.dialog.showOpenDialogSync({
title: "导出报告",
buttonLabel: "导出报告",
properties: ["openDirectory"], //openDirectory选择文件夹
});
if (!res) return;
let fileName = "报告" ;
filePath = this.es.path.join(res[0], `${fileName}.pdf`);
}
let html = this.getExportReportHtml();
this.es.ipcRenderer.send(
"export-pdf",
(<string>"4a3s2f", { filePath, html, mode })
);
this.es.ipcRenderer.once("export-pdf-res", (_e, data) => {
console.log("结果:", data);
if (!data.success) {
this.message.error(data.msg);
}
});
console.log(res);
}
// 获取报告的html代码
getExportReportHtml(): string {
return `
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta name="author" content="CEditor">
<title>导出报告</title>
</head>
<body class="markdown-body code-github">
<h1>41312</h1>
</body>
</html>
`;
}
2.主进程:
ipcMain.on('export-pdf',async (_event,obj)=>{
let pdfWindow:any = new BrowserWindow({
webPreferences: {
nodeIntegration: true,//是否启用Node integration
webSecurity: false,//当设置为 false, 它将禁用同源策略
enableRemoteModule: true
},
show: obj.mode==1?true:false, // 是否显示窗口
width: 1000,
height: 800,
fullscreenable: true,//决定最大化/缩放窗口按钮是切换全屏模式还是最大化窗口
minimizable: false,//设置用户是否可以手动将窗口最小化。 在Linux上不起作用
modal:true,//是否为模态框
center:true,//是否居中显示
icon:'./src/assets/icons/icon.ico',//窗口的图标
// icon:'.\\icon.ico',
});
pdfWindow.loadURL(`data:text/html;charset=utf-8,${encodeURI(obj.html)}`);
if(obj.mode==2){
pdfWindow.webContents.on('did-finish-load', () => {
// Use default printing options
const pdfPath = obj.filePath;
pdfWindow.webContents.printToPDF({
printBackground: true
}).then(data => {
fs.writeFile(pdfPath, data, error => {
if (error) throw error;
win.webContents.send('export-pdf-res', { success: true,msg:`导出成功,路径:${pdfPath}` });
pdfWindow.close();// 保存pdf过后关闭该窗口
pdfWindow = null;
});
}).catch(error => {
win.webContents.send('export-pdf-res', { success:false,msg: `导出失败,路径:${JSON.stringify(error)}` });
});
});
}
})
总结
有什么疑问的地方欢迎评论,我会不定期进行回复。
开放原子开发者工作坊旨在鼓励更多人参与开源活动,与志同道合的开发者们相互交流开发经验、分享开发心得、获取前沿技术趋势。工作坊有多种形式的开发者活动,如meetup、训练营等,主打技术交流,干货满满,真诚地邀请各位开发者共同参与!
更多推荐
所有评论(0)