How to generate QR code images using NodeJS

Nowadays you can find the QR code everywhere and it can come handy to share any URLs, promote your events, share your contact details etc. There are tons of use cases available for QR codes. The definition of a QR code is following,

a machine-readable code consisting of an array of black and white squares, typically used for storing URLs or other information for reading by the camera on a smartphone.

Now let’s learn how we can generate QR codes in our web apps using Nodejs. Our web app will have one text input and one button where we will enter any text or URL which we want to convert to a QR code. On click of the button, we will use AJAx to send the request to our server along with the data and our NodeJS server will convert that text to a QR code and we will get the URL of the generated QR code image as the response on our client side. Our final product will look something like this. You can download the project files at the end of the tutorial.

autocomplte-demo-in-awesomplete

Demo Application

Creating a new project and project structure.

Let’s quickly create a new directory, named as qrcode-demo and initialize it using npm init -y. For our demo app, I am going to use ExpressJs as a server-side framework, EJS as the template engine and to generate a QR code from the text I am going to use a third party package called qr-imageLet’s fire up the following command in your terminal to install all the required node modules,

> npm install express ejs qr-image

Our project structure will look like the following image,

awesomplte-project-structure

Project Strcuture

We have created a directory public which will hold all the folder and files which will be publicly exposed like css files. We have qr directory it will store all the images of QR codes generated by our code.

About the qr-image.

qr-image is a third party node module to convert text to QR code.

Features of qr-image

  • No dependencies.
  • generate an image in, png, svg, eps, and pdf formats.
  • numeric and alphanumeric modes.
  • support UTF-8.

Let’s dive into coding…

For our front end, I am using Bootstrap 4 CSS framework to quickly create our UI for the app

index.ejs

<html lang="en">
  <head>
    <!-- Required meta tags -->
    <meta charset="utf-8" />
    <meta
      name="viewport"
      content="width=device-width, initial-scale=1, shrink-to-fit=no"/>

    <!-- Bootstrap CSS -->
    <link
      rel="stylesheet"
      href="//stackpath.bootstrapcdn.com/bootstrap/4.1.3/css/bootstrap.min.css"
      integrity="sha384-MCw98/SFnGE8fJT3GXwEOngsV7Zt27NXFoaoApmYm81iuXoPkFOJwJ8ERdknLPMO"
      crossorigin="anonymous"/>

    <link rel="stylesheet" href="/css/style.css?x26402">

    <title>QR Code Generator</title>
  </head>
  <body>
    
    <div class="container">
      <div class="row justify-content-center">
        <div class="col-md-6 align-self-center" style="margin-top: 13%;">
          <h1 class="text-center text-light">Convert your text to QR code</h1>
          <form>
            <div class="form-group">
              <label for="input_text"></label>
              <input type="text" class="form-control form-control-lg	" id="input_text" placeholder="Enter Your Text Here">
              
            </div>
            
            <button type="button" id="gen" class="btn btn-primary btn-block">Generate QR Code</button>
          </form>
        </div>
      </div>
      
      <div class="row justify-content-center">
        <div class="col-md-6 align-self-center" style="margin-top: 20px;margin-bottom:5px;margin-left: 30%;">
         
         <img src="" id="qr-code-img" class="img-responsive text-center d-none" alt="Image">
         
        </div>
      </div>
    </div>
    
  
    <script
      src="//stackpath.bootstrapcdn.com/bootstrap/4.1.3/js/bootstrap.min.js"
      integrity="sha384-ChfqqxuZUCnJSK3+MXmPNIyE6ZbWh2IMqE241rYiqJxyMiZ6OW/JmZQ5stwEULTy"
      crossorigin="anonymous"
    ></script>

    <script>
        document.querySelector('#gen').addEventListener('click', function () {
          // Get the text from input
          let txt = document.querySelector('#input_text').value;
          
          // Do not send request if field is empty
          if(txt !== ''){
             var xhttp = new XMLHttpRequest();
            xhttp.onreadystatechange = function () {
              if (this.readyState == 4 && this.status == 200) {
                console.log(this.responseText.qr_img);
                let res = JSON.parse(this.responseText);
                let img = document.querySelector('#qr-code-img');
                // Set img source
                img.src = res.qr_img;

                // Show the image
                img.classList.remove('d-none');

              }
            };
            xhttp.open("POST", "/qrcode", true);
            xhttp.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
            xhttp.send("qr_text=" + txt);
          }
        
        });
    </script>


  </body>
</html>

All the custom css for our app,

style.css

* {
    margin: 0;
    padding: 0
}

body{
    
background: #c5deea; /* Old browsers */
background: -moz-linear-gradient(top, #c5deea 0%, #8abbd7 55%, #066dab 100%); /* FF3.6-15 */
background: -webkit-linear-gradient(top, #c5deea 0%,#8abbd7 55%,#066dab 100%); /* Chrome10-25,Safari5.1-6 */
background: linear-gradient(to bottom, #c5deea 0%,#8abbd7 55%,#066dab 100%); /* W3C, IE10+, FF16+, Chrome26+, Opera12+, Safari7+ */
filter: progid:DXImageTransform.Microsoft.gradient( startColorstr='#c5deea', endColorstr='#066dab',GradientType=0 ); /* IE6-9 */
}

Now let’s code our web app.

First, we need to import all the modules required to achieve the functionality of our web app.

const express = require('express');
const bodyParser = require("body-parser");
const qr = require('qr-image');
const ejs = require('ejs')
const fs = require('fs');

The first module is express which is the heart of our web application. It will do all the heavy lifting for our web app such as creating the server, listening for the request, handling different types of a request such as POST, GET, DELETE etc.

The express module comes with another module called body-parser which actually handles the HTML form data, with this can easily have access to the form data. The third module is the qr-image which will help us to create QR code images from text.

Next module is ejs which is our template engine. The last module is the fs module which is the short form for a file system. This is the built-in module provided by the NodeJS runtime, It provides different methods for file system manipulation.

We require this module to actually create the QR code images. You will come to know the use of it later in the code.

Let’s set up the express, view engine, static folder, and body-parser.

const app = express();

// Set view engine
app.set('view engine', 'ejs')

// Set static folder
app.use(express.static('./public'))

app.use(
  bodyParser.urlencoded({
    extended: true
  })
);

The body parser acts as middleware, What I mean is that it will intercept and parse the incoming request body before any handlers. That’s why we need to place it before any request handler.

Now we need to handle the incoming request. Will require to handle two requests, one for our homepage and one for actually creating the QR codes.

app.get('/', (req, res, next) => {
    res.render('index')
})

app.post('/qrcode', (req, res, next) => {
    // Get the text to generate QR code
    let qr_txt = req.body.qr_text;
    
    // Generate QR Code from text
    var qr_png = qr.imageSync(qr_txt,{ type: 'png'})

    // Generate a random file name 
    let qr_code_file_name = new Date().getTime() + '.png';
 

    fs.writeFileSync('./public/qr/' + qr_code_file_name, qr_png, (err) => {
        
        if(err){
            console.log(err);
        }
        
    })

    // Send the link of generated QR code
    res.send({
        'qr_img': "qr/" + qr_code_file_name
    });

});

When sending the post request to the link /qrcode our request handler will fetch the text we want to convert into QR code with the help of body parser. The qr-imgae module provides the following methods to generate Qr codes.

  • qr.image(text, [ec_level | options]) — Readable stream with image data;
  • qr.imageSync(text, [ec_level | options]) — string with image data. (Buffer for png);
  • qr.svgObject(text, [ec_level | options]) — object with a SVG path and size;
  • qr.matrix(text, [ec_level]) — 2D array.

In our app, we’re going to use the second method to generate the QR code as a PNG image. This method is synchronous which means our next line in the code will not be executed by the NodeJS until it completes its execution If we had used the first method which is asynchronous, In our code, you can see that on the last line we are sending the generated QR image path as a response.

If we don’t use the synchronous method then there are chances that our NodeJS will execute that line and it will send the empty path as a response, as you know that NodeJS is by default asynchronous in nature. The imageSync() takes two parameters, one is text, The text we want to convert to QR code and second is ec_level or options as a JSON object. ec_level represents the error correction level in QR code, you can find out more about error correction levels in QR code on the Internet but for now, we need not worry about it.

We are passing JSON object as options parameter which tells this method how we going to process the Buffer data returned by the method. As you know imageSync() returns the QR image as Buffer, So we need to write that Buffer data to file to generate the QR code image. For this purpose, we are using the fs module.

But before writing the Buffer data to file we need to generate the unique file names for each time we generate new QR code images.

// Generate a random file name 
let qr_code_file_name = new Date().getTime() + '.png';

The above line of code will generate the unique file name based on the current timestamp and we are appending the .png string so that our files can be treated as PNG files by our file system. You create your own way to generate the random unique names but for now, this will suffice our need.

Now on the next line on our code, It’s time to write the buffer data we got from the imageSync() method to a file.The fs module provides a method called writeFileSync() to create a new file asynchronously.

It takes three parameters, First as a file path, second the data to be written to the file, It can be a string or Buffer and third parameter as a callback function. This callback function takes one argument as error If any error occurs during the execution it stores the error in this argument. Finally, our app.js file will look like this,

const express = require('express');
const bodyParser = require("body-parser");
const qr = require('qr-image');
const ejs = require('ejs')
const fs = require('fs');

const app = express();

// Set view engine
app.set('view engine', 'ejs')

// Set static folder
app.use(express.static('./public'))

app.use(
  bodyParser.urlencoded({
    extended: true
  })
);

app.get('/', (req, res, next) => {
    res.render('index')
})

app.post('/qrcode', (req, res, next) => {
    // Get the text to generate QR code
    let qr_txt = req.body.qr_text;
    
    // Generate QR Code from text
    var qr_png = qr.imageSync(qr_txt,{ type: 'png'})

    // Generate a random file name 
    let qr_code_file_name = new Date().getTime() + '.png';

    fs.writeFileSync('./public/qr/' + qr_code_file_name, qr_png, (err) => {
        if(err){
            console.log(err);
        }
        
    })

    // Send the link of generated QR code
    res.send({
        'qr_img': "qr/" + qr_code_file_name
    });

});


app.listen('3000', () => console.log('Server started at port 300'))

Testing the application…

Now it’s time to take a test run of our web app. Let’s enter some text in the input and try to generate a QR code.

qr-code-demo

Working Application

As you can see in the below picture that we have generated and stored the QR code image in our qr folder.

 

Generated QR Code Image

Generated QR Code Image

Now if you scan the above QR code image with your smartphone using and QR code scanner, You will find the same text we have entered in the text input. Let me scan the above QR code with my android phone and show the result.

QR code image scanned result

QR code image scanned result

If you have any suggestions or issues please write it in the comment box….

Happy Coding… 🙂

Click Here To Download The Complete Project

ES10-ES2019 New Features For JavaScript Developers

ES10-ES2019 New Features For JavaScript Developers

Ropali Munshi
Ropali Munshi
Ropali Munshi is fullstack PHP Developer. He is passionate developer who loves to learn and expirement with new programming languages , libraries and frameworks. Nowdays he is more into the JavaScript realm.

Leave a Reply

Your email address will not be published. Required fields are marked *

You Don't Want To Miss It!

Please subscribe to our newsletter. Every week I share tips, tricks, tutorials, free books & video course directly in your inbox.