zoukankan      html  css  js  c++  java
  • Electron 静默打印

    源码

    打印HTML格式

    main进程中

    const path = require('path')
    const {BrowserWindow, app, ipcMain} = require('electron')
    
    const isPrdEnv = process.env.NODE_ENV === 'production'
    const staticPath = isPrdEnv ? './static' : '../../../../static' // 根据当前代码的js相对static文件夹路径
    
    let printWindow = null
    const url = `file://${path.resolve(__dirname, `${staticPath}/print.html`)}`
    
    app.whenReady().then(() => {
        printWindow = new BrowserWindow({
            show: false,
            webPreferences: {
                nodeIntegration: true,
                contextIsolation: false
            }
        })
        printWindow.loadURL(url)
    })
    
    /**
     * 静默打印html
     * @Param content Html字符串
     * @Param deviceName 打印机名称
     * @return promise
     * */
    const htmlToPrint = (content, deviceName, margin) => {
        return new Promise((resolve, reject) => {
            if (!printWindow) return reject('请等待控件加载完成后重试')
            const htmlPrintingListener = () => {
                printWindow.webContents.print({
                    silent: true,
                    printBackground: false,
                    deviceName
                }, (success, failureReason) => {
                    ipcMain.removeListener('htmlPrinting', htmlPrintingListener)
                    if (success) resolve(true)
                    else reject('打印失败')
                })
            }
    
            printWindow.webContents.send('htmlPrint', { content, margin, deviceName })
            ipcMain.on('htmlPrinting', htmlPrintingListener)
        })
    }
    
    
    export default htmlToPrint
    
    

    static文件夹下新建print.html键入以下代码

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <title>Document</title>
    </head>
    
    <body>
    <div id='container'></div>
    </body>
    <script>
        //引入ipcRenderer对象
        const { ipcRenderer } = require('electron')
        ipcRenderer.on('htmlPrint', (e, content) => { //接收响应
            document.querySelector('#container').innerHTML = content
            ipcRenderer.send('htmlPrinting') //向webview所在页面的进程传达消息
        })
    </script>
    </html>
    

    打印网络PDF

    打印本地PDF同理更简单, 未作兼容性处理,详细请看这篇文章,这里需要借助一个第三方软件SumatraPDF 去官网下压缩包解压后放到static文件夹下就行

    main进程中

    
    const path = require('path')
    const https = require('https')
    const fs = require('fs')
    const cp = require('child_process')
    
    const isPrdEnv = process.env.NODE_ENV === 'production'
    const staticPath = isPrdEnv ? './static' : '../../../../static' // 根据当前代码的js相对static文件夹路径
    
    /*
    * 处理await 的异常捕获
    * */
    const awaitWrapper = promise => promise.then(result => [null, result]).catch(error => [error, null])
    
    /*
    * 生成随机字符串
    * */
    const randomString = () => Math.random().toString(36).slice(-6)
    
    /*
    * 获取网络pdf的buffer
    * */
    const getFileBuffer = url => {
        return new Promise(((resolve, reject) => {
            https.get(url, response => {
                const chunks = []
                let size = 0
                response.on('data', chunk => {
                    chunks.push(chunk)
                    size += chunk.length
                })
                response.on('end', () => {
                    const buffer = Buffer.concat(chunks, size)
                    resolve(buffer)
                })
            })
        }))
    }
    
    /*
    * 将buffer保存为本地临时文件
    * */
    const savePdf = buffer => {
        return new Promise((resolve, reject) => {
            const pdfUrl = path.resolve(__dirname, `${staticPath}/${randomString()}.pdf`)
            fs.writeFile(pdfUrl, buffer, {encoding: 'utf8'}, err => {
                if (err) {
                    reject('缓存pdf打印文件失败')
                } else {
                    resolve(pdfUrl)
                }
            })
        })
    }
    
    /*
    * 调用SumatraPDF 执行pdf打印
    * */
    const executePrint = (pdfPath, deviceName) => {
        return new Promise((resolve, reject) => {
            cp.exec(`SumatraPDF.exe -print-to "${deviceName}"  "${pdfPath}"`,
                {
                    windowsHide: true,
                    cwd: path.resolve(__dirname, staticPath)
                },
                e => {
                    if (e) {
                        reject(`${url}在${deviceName}上打印失败`)
                    } else {
                        resolve(true)
                    }
                    /* 打印完成后删除创建的临时文件 */
                    fs.unlink(pdfPath, Function.prototype)
                })
        })
    }
    
    /*
    * 静默打印pdf
    * */
    const pdfToPrint = (url, deviceName) => {
        return new Promise(async (resolve, reject) => {
            /* 根据url获取buffer并返回,如果获取失败就直接reject */
            const [bufferError, buffer] = await awaitWrapper(getFileBuffer(url))
            if (bufferError) return reject('获取网络pdf文件信息失败')
            /* 根据buffer将文件缓存到本地并返回临时pdf文件路径,如果存储失败就直接reject */
            const [pdfPathError, pdfPath] = await awaitWrapper(savePdf(buffer))
            if (pdfPathError) return reject(pdfPathError)
            /* 根据临时pdf文件路径 和打印机名称来执行打印*/
            const [execPrintError, printResult] = await awaitWrapper(executePrint(pdfPath, deviceName))
            if (execPrintError) {
                reject(execPrintError)
            } else {
                resolve(printResult)
            }
        })
    }
    

    关键事项

    package.json中

    1.打包static目录的文件没有打包进去,需要在package.json 里面添加extraResources 额外资源
    2.打包后远程下载pdf无法放入/static下,原因是electron-vue 默认是用asar打包,而asar只能读取不能写入,所以需要远程打印pdf就不能打包成asar

       "win": {
             "icon": "dist/electron/static/icon2.ico",
             "extraResources": [
                "./static/*.html",
                "./static/*.txt",
                "./static/*.exe",
                "./static/*.pdf"
             ],
             "asar": false
        }
    
    为之则易,不为则难。
  • 相关阅读:
    [BZOJ2839:]集合计数
    [BZOJ2863:]愤怒的元首
    [BZOJ:3162]:独钓寒江雪
    PHP数据库基础(简单的)
    PHP数组创建和遍历(基础)
    中缀表达式转换为前、后缀表达式转化简单的技巧[转]
    PHP网页简单的计算机源代码
    JS确认取消按钮使用
    js(JavaScript)使用${pageContext.request.contextPath}报错
    易游验证怎么配置?易游验证怎么使用!!
  • 原文地址:https://www.cnblogs.com/coderDemo/p/14450853.html
Copyright © 2011-2022 走看看