PDFs are among the most widely used formats for business documents, so properly securing them is a critical part of many workflows. If you’re building a web application that needs to open PDFs, you’ll probably run into a situation where you have to deal with password-protected documents. Building this functionality yourself will require a lot of time and maintenance costs that may not be on the roadmap for your team.

Foxit’s JavaScript PDF library makes it easy to display PDFs in a browser-based application. In this tutorial, you’ll set up a Node app that uses Foxit PDF SDK for Web to open password-protected PDFs in the browser and let authorized users preview the document. This application is also available on GitHub if you’d like to jump straight to a working version.

Building a Web Application to Display Password-Protected PDFs

HTML comes with built-in file upload features that allow users to work with files from their local machine in the browser. Unfortunately, displaying PDFs in JavaScript is a bit more complicated, especially when you need to support password protection. In this tutorial, you’ll build a web application with a PDF upload form and an optional password field. When a password-protected PDF is uploaded, and the correct password entered, users will see a preview of the file. If an incorrect password is entered, they’ll be shown an error message and instructed to try again.

You’ll use the Express web framework, Pure CSS for styling, and Foxit’s PDF SDK to build this application.

Prerequisites

NodeJS version 8+ and NPM version 5+

– Foxit PDF SDK for Web (a free trial download is available here)

– Your Foxit license key and serial number

Creating a New Express App

The Express generator makes it easy to set up a new application. From your terminal, run the following:

npx express-generator --git --view=hbs

This command creates a new application with a `.gitignore` file and Handlebars template files.

Next, add the dotenv npm package (which you’ll use to access your Foxit license key and serial number) and install Express’ dependencies:

npm i dotenv && npm i

Assuming you’ve downloaded Foxit PDF SDK for Web, you can find your license key and serial number in the `examples/license-key.js` file. Create a new file at the root directory of your web application called `.env` and add the two values:

LICENSE_SN=""
LICENSE_KEY=””

Next, copy the Foxit library into your web application so you can access it from the front end. Copy the `lib/` directory from Foxit PDF SDK you downloaded and paste it into your web application’s `public/` directory. Now the Foxit JavaScript PDF library will be available in your web application.

Finally, you don’t want sensitive information or proprietary packages to end up in version control, so add the following to your `.gitignore` file:

...
public/lib/
.env

Your web application now has all the dependencies it needs, so in the next step, you’ll create the route that will display the PDF preview using Foxit.

Setting Up the Route

Every page in an Express application has a route, including the PDF upload page you’ll create in this demo. Update the `routes/index.js` file to pass the license key and serial number to the view:

var express = require('express');
var router = express.Router();
router.get('/', function(req, res, next) {
res.render('index', {
licenseSN: process.env.LICENSE_SN,
licenseKey: process.env.LICENSE_KEY,
});
});
module.exports = router;

This allows you to easily update your credentials on the server without hard-coded credentials that require a code change. It also means you can restrict which users can see the Foxit credentials if you add an authentication layer to this application.

Before the `process.env` variables are available, you need to include the `dotenv` library which loads variables from your `.env` file. Open `app.js` and add the following to the top of the file:

require('dotenv').config();
...

Your `LICENSE_SN` and `LICENSE_KEY` are being securely stored and passed to the front end only when required. In the next step, you will address the display portion of the web application.

Uploading and Displaying PDFs

Foxit PDF SDK will handle most of the work to check the password and display the PDF to the user, but you’ll need to implement the user interface for file and password inputs. Before you get to that, you’ll also need to update the layout to include some base styles and scale the `viewport`. This ensures that the PDF preview is sized to the user’s display.

Open the `views/layout.hbs` file and replace it with the following:

<!DOCTYPE html> 
<html lang="en"> 
<head> 
  <title>Foxit PDF Previewer</title> 
  <meta charset="UTF-8"> 
  <meta name="viewport" content="width=device-width,initial-scale=1,minimum-scale=1,maximum-scale=1,user-scalable=no"/> 
  <link rel="stylesheet" href="https://unpkg.com/purecss@2.0.3/build/pure-min.css" integrity="sha384-cg6SkqEOCV1NbJoCu11+bm0NvBRc8IYLRGXkmNrqUBfTjmMYwNKPWBTIKyw9mHNJ" crossorigin="anonymous"> 
  <link rel='stylesheet' href='/stylesheets/style.css' /> 
</head> 
<body> 
<div class="container"> 
  {{{body}}} 
</div> 
</body> 
</html> 

This loads the PureCSS styling library, but you can use any other front end styling framework you’re comfortable with. 

Next, open the `views/index.hbs` file and replace it with the following: 

<h1>PDF Previewer</h1> 
<p>Use the form below to preview any password-protected PDF file in this web application.</p> 

<!-- PDF Upload form --> 
<form class="pure-form"> 
  <fieldset> 
    <input type="password" id="password" placeholder="Enter PDF Password" /> 
    <input class="original-pdf-upload-button" type="file" name="file" id="file" accept=".pdf,.fdf,.xfdf" multiple="multiple" /> 
    <label class="pure-button new-pdf-upload-button" for="file">Select a PDF file</label> 
  </fieldset> 
</form> 

 <!-- PDF Display Div --> 
<div id="pdf-viewer"></div> 

 <!-- Foxit and custom JavaScript --> 
<script src="/lib/PDFViewCtrl.full.js"></script> 
<script> 
  var PDFViewer = PDFViewCtrl.PDFViewer; 
  var pdfViewer = new PDFViewer({ 
    libPath: '/lib', 
    jr: { 
      licenseSN: "{{ licenseSN }}", 
      licenseKey: "{{ licenseKey }}", 
    }, 
  }); 
  pdfViewer.init('#pdf-viewer'); 
  
  document.getElementById('file').onchange = function (e) { 
    if (!this.value) { 
      return; 
    } 
    var pdf,fdf; 
    for (var i = e.target.files.length; i--;) { 
      var file = e.target.files[i]; 
      var filename = file.name; 
      if (/\.pdf$/i.test(filename)) { 
        pdf = file 
      } else if (/\.(x)?fdf$/i.test(filename)) { 
        fdf = file 
      } 
    } 
    var options = {password: '', fdf: {file: fdf}}; 
    if (document.getElementById('password').value) { 
      options.password = document.getElementById('password').value; 
      document.getElementById('password').value = ''; 
    } 
    pdfViewer.openPDFByFile(pdf, options); 
    this.value = ''; 
  }; 
</script> 

This file serves three purposes. First, it includes a PDF upload form with a password field. The file upload input element also has a `<label>`, which acts as a nicely styled upload button. Next, the `<div id=”pdf-viewer”>` tag wraps the Foxit PDF reader which is used in the `pdfViewer.init` function in the custom JavaScript. The last section of this file loads Foxit’s `PDFViewCtrl.PDFViewer` class and initializes it using the code inside the `<script>` tags. 

Your application’s functionality is just about done, but before you test this, open up your `public/stylesheets/style.css` file and replace it with the following: 

body { 
  background-color: #f7f7f7; 
  color: #333333; 
} 
.container { 
  background-color: #ffffff; 
  margin: 0 auto; 
  padding: 30px; 
} 
/* File upload button styling */ 
.original-pdf-upload-button { 
  width: 0.1px; 
  height: 0.1px; 
  opacity: 0; 
  overflow: hidden; 
  position: absolute; 
  z-index: -1; 
} 
  .new-pdf-upload-button { 
  top: -2px; 
  position: relative; 
} 

This will style the PDF upload button such that it’s consistent with the other PureCSS buttons and give your application a bit of padding. 

To test the application, save your work and run `npm start` from your terminal. Node will spin up a server, and your web app will be available at `localhost:3000`. 

 

If you have a password-protected document on your computer, type the password into the input box, then upload the PDF file. If your password is correct, the file will be uploaded, and the password removed from the input box. This is a start, but what happens if a user types an incorrect password? You probably want to let them know so they can try again, and in the final step, you’ll address this. 
 

Handling Errors 

Foxit’s `pdfViewer.openPDFByFile` method returns a promise, so if you want to know when it resolves, you need to add a callback to the `then` or `catch` methods. 

In your `views/index.hbs` file, replace the `pdfViewer.openPDFByFile…` line with the following: 

... 
    pdfViewer.openPDFByFile(pdf, options) 
      .catch(error => { 
        console.error(error); 
        document.getElementById('wrong-password').style.display = 'block'; 
      }); 
... 

And add a new paragraph element to the top of the file with the `id=”wrong-password”`: 

<p id="wrong-password" class="error"><strong>Whoops!</strong> 
  It looks like the password you entered was incorrect. 
  Please enter a password and try uploading your file again. 
</p> 
...

Finally, you’ll need some styling for that error message so that it’s only shown when the `catch` method is called. In your `public/stylesheets/style.css` file, add the following: 

... 
#wrong-password { 
  display: none; 
} 
.error { 
  background-color: #f5c0c0; 
  color: #792525; 
  padding: 10px; 
} 

Now when you enter an incorrect password (or leave the field blank) and upload a password-protected PDF, you’ll see an error message letting you know that something went wrong: 

 

In this tutorial, you’ve seen how to build a Node web application that allows users to preview password-protected PDFs in their browser securely. Using Foxit PDF SDK will save you countless hours of development time, and our tools come with an array of other examples in the documentation. While this tutorial has focused on building a web application, we provide PDF SDKs for many platforms including mobile and native apps.