使用Electron JS打印PDF文件

Gri*_*don 22 javascript printing pdf node.js electron

我正在尝试创建一个Electron JS应用程序,其目的是打印字母大小的PDF.

这是我的打印代码片段:

win = new BrowserWindow({
  width: 378, 
  height: 566, 
  show: true, 
  webPreferences: {
    webSecurity: false,
    plugins: true
  }
});

// load PDF
win.loadURL('file://' + __dirname + '/header1_X_BTR.pdf');

// if pdf is loaded start printing
win.webContents.on('did-finish-load', () => {
  win.webContents.print({silent: true, printBackground:true});
});
Run Code Online (Sandbox Code Playgroud)

我的问题是:如果我让print({silent:true})我的打印机打印一个空页面.如果有print({silent:false}),打印机的打印方式与屏幕截图相同,包括标题,控件等.

在此输入图像描述

我需要对PDF内容进行静音打印,而且我无法在数天内完成这项工作.有没有人与Electron有同样的经历?

nos*_*tio 5

我面临同样的问题。尽管自 2017 年以来就有人要求将 PDF 打印到打印机,但它似乎并未在 Electron 中实现。这是关于 SO 的另一个相关问题和 GitHub 上的功能请求:

一个可能的解决方案可能是使用Google PDFium和一个包装NodeJS,它似乎允许从 PDF 转换为一组 EMF,因此 EMF 可以打印到本地/网络打印机,至少在 Windows 上。

作为另一个可行的选择,这个答案为使用PdfiumViewer 的PDF 打印提供了一个简单的 C# 解决方案,它是一个用于 .NET 的 PDFium 包装库。

我还在考虑任何其他选择。使用本地安装的 Acrobat Reader 实例进行打印不是我们可接受的解决方案。


更新。目前,PDF.js解决了渲染/预览单个页面的问题,但至于打印本身,似乎 Electron(在本文发布时)只是缺乏适当的打印 API。例如,您无法设置纸张大小/横向纵向模式等。此外,在打印时,PDF.js 会生成光栅化打印输出——这要归功于 HTML5 画布的工作方式——与 Chrome PDF 查看器的工作方式不同。这是对其他一些 PDF.js 缺点的讨论

所以现在我认为我们可能会继续使用 PDF.js(用于 Electron 渲染器进程中的 UI)和 PDFium(用于从 Main 进程进行实际打印)的组合。

根据Tim 的回答,这里有一个使用 ES8 的 PDF.js 渲染器版本async/await(从当前版本的 Electron 开始支持):

async function renderPDF(url, canvasContainer, options) {
    options = options || { scale: 1 };

    async function renderPage(page) {
        let viewport = page.getViewport(options.scale);
        let canvas = document.createElement('canvas');
        let ctx = canvas.getContext('2d');
        let renderContext = {
            canvasContext: ctx,
            viewport: viewport
        };

        canvas.height = viewport.height;
        canvas.width = viewport.width;
        canvasContainer.appendChild(canvas);

        await page.render(renderContext);
    }

    let pdfDoc = await pdfjsLib.getDocument(url);

    for (let num = 1; num <= pdfDoc.numPages; num++)
    {
        if (num > 1)
        {
            // page separator
            canvasContainer.appendChild(document.createElement('hr'));
        }
        let page = await pdfDoc.getPage(num);
        await renderPage(page);
    }
}
Run Code Online (Sandbox Code Playgroud)


zer*_*r09 5

如果您已经有了pdf文件,或者在打印“我认为是”之前保存了pdf,则可以获取文件位置,然后可以使用外部过程进行打印child_process

您可以使用Windows lp commandPDFtoPrinter

const ch = require('os');

switch (process.platform) {
    case 'darwin':
    case 'linux':
        ch.exec(
            'lp ' + pdf.filename, (e) => {
                if (e) {
                    throw e;
                }
            });
        break;
    case 'win32':
        ch.exec(
            'ptp ' + pdf.filename, {
                windowsHide: true
            }, (e) => {
                if (e) {
                    throw e;
                }
            });
        break;
    default:
        throw new Error(
            'Platform not supported.'
        );
}
Run Code Online (Sandbox Code Playgroud)

希望对您有所帮助。

编辑: 您也可以将SumatraPDF用于Windows https://github.com/sumatrapdfreader/sumatrapdf


Tim*_*Tim 5

最简单的方法是使用PDF.js将PDF页面呈现为页面上各个画布元素,然后调用print。

我修复了这个要点,以使用它设计的PDF.js版本(v1),这可能是一个很好的起点。

这实质上是电子/铬pdf查看器的工作,但是现在您可以完全控制布局了!

<html>
<body>
<script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/pdf.js/1.10.90/pdf.js"></script>
<script type="text/javascript">
function renderPDF(url, canvasContainer, options) {
    var options = options || { scale: 1 };
        
    function renderPage(page) {
        var viewport = page.getViewport(options.scale);
        var canvas = document.createElement('canvas');
        var ctx = canvas.getContext('2d');
        var renderContext = {
          canvasContext: ctx,
          viewport: viewport
        };
        
        canvas.height = viewport.height;
        canvas.width = viewport.width;
        canvasContainer.appendChild(canvas);
        
        page.render(renderContext);
    }
    
    function renderPages(pdfDoc) {
        for(var num = 1; num <= pdfDoc.numPages; num++)
            pdfDoc.getPage(num).then(renderPage);
    }
    PDFJS.disableWorker = true;
    PDFJS.getDocument(url).then(renderPages);
}   
</script> 

<div id="holder"></div>

<script type="text/javascript">
renderPDF('//cdn.mozilla.net/pdfjs/helloworld.pdf', document.getElementById('holder'));
</script>  

</body>
</html>
Run Code Online (Sandbox Code Playgroud)