How to generate pdf using nodejs, express and mysql with pdfkit

Generate pdf using nodejs

In dynamic web applications developers often need to export data in pdf, csv, rss or xml formats. NodeJS have many libraries and modules that are used to produce such kind of output. A previous tutorial explored how to zip and unzip files using nodejs. In this tutorial you are going to learn how to generate pdf using nodejs, express and mysqlpdfkit module is used to generate pdf and node orm is used to connect to database and fetch records.

Following tasks are going to be performed in this tutorial.

1. Create a MySQL database and table for news posts

2. Generate an express application

3. Install pdfkit and orm modules using NPM

4. Display records from database using node orm module

5. Using pdfkit module to generate pdf using nodejs

generate pdf using nodejs - final app

Create a News MySQL database

First you need to create a MySQL database and a table for news posts using PhpMyAdmin. To install PhpMyAdmin, download WAMP or  XAMPP and install on your system. After installation open PhpMyAdmin and click SQL tab. Execute queries given below.

Sample news posts from BBC and Tech News World site are inserted in to database.
CREATE DATABASE IF NOT EXISTS dbnews DEFAULT CHARACTER SET latin1 COLLATE latin1_swedish_ci;

USE dbnews;

--
-- Table structure for table tbl_posts
--

CREATE TABLE tbl_posts (

  id int(11) NOT NULL,

  title varchar(500) NOT NULL,

  detail text NOT NULL,

  publish_date datetime NOT NULL,

  author_name varchar(200) NOT NULL,

  link varchar(200) NOT NULL

) ENGINE=InnoDB DEFAULT CHARSET=latin1;

--
-- Dumping data for table tbl_posts
--

INSERT INTO tbl_posts (id, title, detail, publish_date, author_name, link) VALUES

(1, 'Raspberry Pi scores UK\'s top engineering award', 'The team behind the device was awarded the Royal Academy of Engineering\'s MacRobert Prize at a ceremony in London last night.\r\n\r\nThe tiny computer launched in 2012. Its designers hoped to introduce children to coding and had modest ambitions.\r\n\r\nThey beat two other finalists, cyber-security company Darktrace and radiotherapy pioneers Vision RT, to win the prize.\r\n\r\nPrevious winners of the innovation award, which has been run since 1969, include the creators of the CT (computerised tomography) scanner; the designers of the Severn Bridge; and the team at Microsoft in Cambridge that developed the Kinect motion sensor.\r\nExceeded expectations\r\n\r\nA tiny cheap computer that might encourage youngsters to learn programming was the idea of a small team of scientists and Cambridge University academics.\r\n\r\nThey hoped to sell a few thousand units, but sales have now passed 14 million, and the Pi is widely used in factories as well as in classrooms and homes.\r\n\r\nOne of the MacRobert award judges, Dr Frances Saunders, said a small engineering team had redefined home computing.', '2017-07-02 00:00:00', 'BBC News', 'http://www.bbc.com/news/technology-40444356'),

(2, 'Future Energy: China leads world in solar power production', 'Ten years ago, Geof Moser had just graduated with a master\'s degree in solar energy from Arizona State University - but he didn\'t feel much opportunity lay at his feet in his home country.\r\n\r\nSo he headed for China.\r\n\r\n\"The solar industry was fairly small and there weren\'t a lot of jobs,\" he remembers. \"Just a few for installation.\" But the Chinese government had big ambitions to expand solar and Moser saw his chance.\r\n\r\nHe spent some years accumulating knowledge about the Chinese solar industry, before co-founding Symtech Solar, which designs solar panel systems using Chinese parts.\r\nMarket access\r\n\r\nThe idea is to make it easy for organisations outside China to access components without the hassle of having to source and assemble lots of different parts. ', '2017-07-02 00:00:00', 'BBC News', 'http://www.bbc.com/news/business-40341833'),

(3, 'Securing Your Linux System Bit by Bit', 'As daunting as securing your Linux system might seem, one thing to remember is that every extra step makes a difference. It\'s almost always better to make a modest stride than let uncertainty keep you from starting. Fortunately, there are a few basic techniques that greatly benefit users at all levels, and knowing how to securely wipe your hard drive in Linux is one of them.', '2017-07-02 00:00:00', 'Tech World', 'http://www.technewsworld.com/story/Securing-Your-Linux-System-Bit-by-Bit-84607.html');

--
-- Indexes for table tbl_posts
--

ALTER TABLE tbl_posts
  ADD PRIMARY KEY (id);

--
-- AUTO_INCREMENT for table tbl_posts
--

ALTER TABLE tbl_posts
  MODIFY id int(11) NOT NULL AUTO_INCREMENT, AUTO_INCREMENT=4;COMMIT;

generate pdf using nodejs

Generate a NodeJS application

To generate pdf using nodejs, you need to generate a nodejs, express application using Express tool on command line. First install express generator. To install express generator, type following command on command line.

npm install express-generator -g

Express application to generate pdf using nodejs

Express tool is used to generate an express application skeleton. pug is used as template engine for view files.

express --view=pug generate-pdf-using-nodejs

generate pdf using nodejs

After application is generated, install required modules using npm install.

cd generate-pdf-using-nodejs && npm install

To run the application, type

Set debug = generate-pdf-using-nodejs:*  &npm start

or

node bin/www

To view application in browser, open browser and type URL

http://localhost:3000

By default nodejs application runs on port 3000. You can stop a nodejs application by pressing ctrl+c on command line.

Install node ORM and create news model

On command line type command below to install Node ORM module.

npm install orm

This command installs node orm. ORM is used to map database objects and perform database related tasks and queries easily.

Update index.js to generate pdf using nodejs

Open index.js file in routes folder and add following code.

var orm         = require('orm');

router.use(orm.express("mysql://root:@localhost:/dbnews", {

  define: function (db, models, next) {

    models.news = db.define("tbl_posts", {

    id           : Number,

    title        : String,

    detail       : String,

    author_name  : String,

    link         : String,

    publish_date : { type: 'date', time: false },

  });

  next();

  }

}));

In the code orm  module is included and assigned to orm variable. Next router.use method is used and a model is created inside orm.express and connected to dbnews database. If there is a password on your system for database user, you can specify after username like username:password@localhost.

Inside function db object and a model is defined for tbl_posts and is assigned it to models.news. Table structure for tbl_posts  with id, title, detailsauthor name and publish date columns are assigned to model.

Update ‘/’ route to display records

Open index.js file in routes folder and add code given below.

var result = req.models.news.find({

}, function(error, news){

    if(error) throw error;

    res.render('index', { news:news, title: 'Generate PDF using NodeJS' });

});

News model’s find method is used to find all records. You can see empty {} here. This is criteria, as no criteria is used in this method so all records are selected from database. In callback function, error and news are parameters are passed. News array is assigned to index view file.

Update index.pug file

Open index.pug file in views folder. Add code under block content to display fetched records from database.

h1= title

  p Click on generate PDF link to Generate PDF using NodeJS and Express

  table.table.table-hover.table-striped.table-bordered

    thead

      tr

        th #

        th Title

        th Author

        th Action
    tbody

    - for (var i = 0; i < news.length; ++i) {

       tr

         th(scope='row') #{i+1}

         td #{news[i]['title']}

         td #{news[i]['author_name']}

         td

          a(href="/pdf?id="+news[i]['id'])

           | Generate PDF

    - }

In page above HTML table is displayed with table headings #, Title, Author and Action. Inside tbody section all news items are displayed in a loop. A link Generate PDF is added against each record. Open browser and type this URL.

http://localhost:3000

generate pdf using nodejs

Add /pdf route to generate pdf using nodejs

When a user clicks on Generate PDF link, /pdf  route is executed. Id of the post is passed to route and database record is fetched from database using find method of news model. PDF is generated using pdfkit module, so first install pdfkit module. Open command line.

npm install pdfkit

Open index.js in routes folder and add this line.

var PDFDocument = require('pdfkit');

After ‘/’ route add following code.

router.get('/pdf', function(req, res, next) {

  var id  = req.query.id;

  const doc = new PDFDocument();

  var result = req.models.news.find({id: id}, function(error, newspost){

      if(error) throw error;

      var title        = newspost[0]['title'];

      var content      = newspost[0]['detail'];

      var publish_date = newspost[0]['publish_date'];

      var author_name  = newspost[0]['author_name'];

      var link         = newspost[0]['link'];

      var filename     = encodeURIComponent(title) + '.pdf';

      res.setHeader('Content-disposition', 'attachment; filename="' + filename + '"');

      res.setHeader('Content-type', 'application/pdf');

      doc.font('Times-Roman', 18)
        .fontSize(25)
        .text(title, 100, 50);

      doc.fontSize(15)
         .fillColor('blue')
         .text('Read Full Article', 100, 100)
         .link(100, 100, 160, 27, link);

      doc.moveDown()
         .fillColor('red')
         .text("Author: "+author_name);
      
      doc.moveDown()
         .fillColor('black')
         .fontSize(15)
         .text(content, {
           align: 'justify',
           indent: 30,
           height: 300,
           ellipsis: true
         });
      
     doc.pipe(res);
      
     doc.end();
  
  });

As you can see a new route ‘/pdf’ is created. Inside route req.query.id gets id parameter from URL query string. Next an object of pdfDocument is created.

News post id is passed to model.find method. In callback method the data of this new post is fetched and assigned to newspost array. Then title, detail, publish date, author name and link values are assigned to variables.

Generate PDF from database record

Title of news post is used as PDF file name and is assigned to filename variable. Headers are also set. Headers are used to pass any additional data to server or client. Here content type of file application/pdf is passed to user’s browser.

Next font family with font size, x and y position are assigned to text for title of document. Under title link to original news is added with fill color as blue. After link author name is added with red fill color.

Detail of post is added to pdf document with fill color black and font size 15. Inside text property detail  is assigned from database, alignment is justified with 30px indentation and a height with 300px. Lastly doc object contents are stream to response object. User is prompted to save the pdf file.

generate pdf using nodejs

 

generate pdf using nodejs

You can see a pdf generated above. To get more information about pdf options you can visit pdfkit site.

Summary

To summarize in this tutorial we have created a MySQL database to save news, installed ORM and pdfkit modules. Records from database are displayed. Clicking on Generate PDF link of a news generates pdf file. Click here to download source code used in this tutorial.

Please leave your feedback and comments. Follow us  on twitter to get information about upcoming tutorials.