Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to view a PDF in an Electron BrowserWindow?

So I have this Electron app and in one of the .html-files I link another script that provides some utility-functions to the program and one of those is this one:

function openPDF(filePath){
    let pdfWindow = new electron.remote.BrowserWindow({
        icon: './build/icon.png',
        width: 1200,
        height: 800,
        webPreferences: {
            plugins: true
        }
    });

    pdfWindow.loadURL(url.format({
        pathname: filePath,
        protocol: 'file:',
        slashes: true
    }));

    pdfWindow.setMenu(null);

    pdfWindow.on("closed", function () {
        pdfWindow = null
    });
}

So this should use the integrated PDF-Viewer of Electron (which uses Chromium) to open the PDF in a new window. I used the infamous plugins: true, I tried through most of the thousands of preferences you can define for a BrowserWindow but it always opens the window and then starts to download the file instead of displaying it.

I triple checked the file path, the "imports" etc., updated everything but I can't seem to find the problem. Electron natively supports this since 1.6.4 but it doesn't work for me.

Help me, Stack Overflow, you are my only hope.

like image 842
leonheess Avatar asked Oct 16 '18 21:10

leonheess


1 Answers

Update 2020:

@karthick correctly pointed out that this is a bug that disables the plugins despite plugins: true. The Issue exists since 3.0.0 (September 18, 2018) and remains to be fixed today has finally been fixed in Version 9!

Update your electron version to 9.X.X or higher with this command to enable the functionality:

npm update electron

You can check the devDependencies in the package.json which should be found in your project folder. It should look something like this:

"devDependencies": {
    "electron": "^9.0.0"
},

Old answer:

As long-lasting GitHub issues tend to get rather confusing I will update this answer with the gist of the development. You can also find three workarounds at the end of the answer.

Updates:

  1. March 19th: A fix is on the way.
  2. May 19th: The fix mentioned above is currently on hold waiting for better extension support.
  3. June 28th: Better extension support is not expected to be there any time soon.
  4. July 16th: The fix is no longer being actively worked on. Quote of the developer:

The main thing I ran into trying to port over Chromium's viewer was its dependency on the chromium extension system. Electron supports only a portion of that system which made it difficult to integrate the viewer.

  1. July 25th: There has been significant progress with the improvement of the extension support which was merged and a follow-up tracking issue was created. This increased the likeliness of a continuation of the work on the fix.

  2. August 28th: Right now no one is working on a fix. You can put a bounty on this issue over on BountySource if you want to see this solved more quickly.

  3. November 19th: The fix was closed and the branch deleted. Quote of the developer:

We're still intending to one day restore the PDF viewer, but it relies on us first migrating to use Chrome's extensions library instead of our own shim, as the PDF viewer in Chromium is implemented as an extension.

  1. January 2nd: Still no one is working on this despite a bounty of $1,600 over on BountySource

  2. January 21st: Extension support is being improved continuously (tracking issue) and a new fix has been introduced.

  3. February 13th: The new fix has been merged and the issue has been closed. Looks like this is going to be resolved in Electron 10! Quote of the developer:

This should be ready to test out in the next 10.x nightly. I'm hoping to backport to 9.x as well, though it may not end up sticking if it causes issues.

Workarounds:

  1. You can make it work by downgrading to the latest 2.X.X. To do that use the following command:

     npm install electron@"<3.0.0" --save-dev
    

Keep in mind, however, that only the latest three stable major versions are supported by the Electron team which means 2.X.X is not receiving security patches anymore.

  1. Alternatively you could call on the system to open the file. It will choose the default program assigned to PDFs:

     shell.openItem(fullPath);
    

Just make sure that the path (fullPath) is always correctly resolved with something like path.resolve(app.getAppPath(), filePath) as it might change when you build the app.

  1. Another workaround would be to use something like PDF.js which doesn't quite offer the full feature set of the Chrome PDF Viewer (e.g. missing field completion) but is probably good enough for most applications. Here is a sample implementation which catches the download-event and routes it to the PDF.js-viewer:

     const { BrowserWindow, session } = require('electron')
     session.defaultSession.on('will-download', (event, item, webContents) => {
         if (item.getMimeType() === 'application/pdf' && item.getURL().indexOf('blob:file:') != 0) {
             event.preventDefault();
             new BrowserWindow().loadFile(path.resolve(__dirname, `pdfjs/web/viewer.html?file=${item.getURL()}`));
         }
     })
    
like image 179
leonheess Avatar answered Oct 19 '22 06:10

leonheess