Silent printing in electron

前端 未结 3 855
佛祖请我去吃肉
佛祖请我去吃肉 2021-02-06 10:35

I am currently building an electron app. I have a PDF on my local file system which I need to silently print out (on the default printer). I came across the node-printer library

相关标签:
3条回答
  • 2021-02-06 11:12

    I recently published NPM package to print PDF files from Node.js and Electron. You can send a PDF file to the default printer or to a specific one. Works fine on Windows and Unix-like operating systems: https://github.com/artiebits/pdf-to-printer.

    It's easy to install, just (if using yarn):

    yarn add pdf-to-printer
    

    or (if using npm):

    npm install --save pdf-to-printer
    

    Then, to silently print the file to the default printer you do:

    import printer from "pdf-to-printer";
    
    printer
      .print("assets/pdf-sample.pdf")
      .then(console.log)
      .catch(console.error);
    
    0 讨论(0)
  • 2021-02-06 11:16

    To my knowledge there is currently no way to do this directly using Electron because while using contents.print([]) does allow for 'silently' printing HTML files, it isn't able to print PDF views. This is currently an open feature request: https://github.com/electron/electron/issues/9029

    Edit: I managed to work around this by converting the PDF to a PNG and then using Electron's print functionality (which is able to print PNGs) to print the image based view. One of the major downsides to this is that all of the PDF to PNG/JPEG conversion libraries for NodeJS have a number of dependencies, meaning I had to implement them in an Express server and then have my Electron app send all PDFs to the server for conversion. It's not a great option, but it does work.

    0 讨论(0)
  • 2021-02-06 11:18

    Well first of all it is near impossible to understand what you mean with "silent" print. Because once you send a print order to your system printer it will be out of your hand to be silent at all. On Windows for example once the order was given, at least the systemtray icon will indicate that something is going on. That said, there are very good described features for printing with electron even "silent" is one of them:

    You need to get all system printers if you do not want to use the default printer:

    contents.getPrinters()
    

    Which will return a PrinterInfo[] Object.

    Here is an example how the object will look like from the electron PrtinerInfo Docs:

    {
      name: 'Zebra_LP2844',
      description: 'Zebra LP2844',
      status: 3,
      isDefault: false,
      options: {
        copies: '1',
        'device-uri': 'usb://Zebra/LP2844?location=14200000',
        finishings: '3',
        'job-cancel-after': '10800',
        'job-hold-until': 'no-hold',
        'job-priority': '50',
        'job-sheets': 'none,none',
        'marker-change-time': '0',
        'number-up': '1',
        'printer-commands': 'none',
        'printer-info': 'Zebra LP2844',
        'printer-is-accepting-jobs': 'true',
        'printer-is-shared': 'true',
        'printer-location': '',
        'printer-make-and-model': 'Zebra EPL2 Label Printer',
        'printer-state': '3',
        'printer-state-change-time': '1484872644',
        'printer-state-reasons': 'offline-report',
        'printer-type': '36932',
        'printer-uri-supported': 'ipp://localhost/printers/Zebra_LP2844',
        system_driverinfo: 'Z'
      }
    }
    

    To print your file you can do it with

    contents.print([options])
    

    The options are descriped in the docs for contents.print():

    • options Object (optional):
    • silent Boolean (optional) - Don’t ask user for print settings. Default is false.
    • printBackground Boolean (optional) - Also prints the background color and image of the web page. Default is false.
    • deviceName String (optional) - Set the printer device name to use. Default is ''.

    Prints window’s web page. When silent is set to true, Electron will pick the system’s default printer if deviceName is empty and the default settings for printing.

    Calling window.print() in web page is equivalent to calling webContents.print({silent: false, printBackground: false, deviceName: ''}).

    Use page-break-before: always; CSS style to force to print to a new page.

    So all you need is to load the PDF into a hidden window and then fire the print method implemented in electron with the flag set to silent.

    // In the main process.
    const {app, BrowserWindow} = require('electron');
    let win = null;
    
    app.on('ready', () => {
      // Create window
      win = new BrowserWindow({width: 800, height: 600, show: false });
      // Could be redundant, try if you need this.
      win.once('ready-to-show', () => win.hide())
      // load PDF.
      win.loadURL(`file://directory/to/pdf/document.pdf`);
     // if pdf is loaded start printing.
      win.webContents.on('did-finish-load', () => {
        win.webContents.print({silent: true});
        // close window after print order.
        win = null;
      });
    });
    

    However let me give you a little warning: Once you start printing it can and will get frustrating because there are drivers out there which will interpret data in a slightly different way. Meaning that margins could be ignored and much more. Since you already have a PDF this problem will most likely not happen. But keep this in mind if you ever want to use this method for example contents.printToPDF(options, callback). That beeing said there are plently of options to avoid getting frustrated like using a predefined stylesheet like descriped in this question: Print: How to stick footer on every page to the bottom?

    If you want to search for features in electron and you do not know where they could be hidden, all you have to do is to go to "all" docs and use your search function: https://electron.atom.io/docs/all/

    regards, Megajin

    0 讨论(0)
提交回复
热议问题