Node.js Express Script to Compress PDF Online to Smaller Size Using GhostScript Library Full Project With Deployment 2021

Node.js Express Script to Compress PDF Online to Smaller Size Using GhostScript Library Full Project With Deployment 2021

 

 

 

Welcome folks today in this post we will be talking about how to compress pdf documents to smaller size in node.js and express using a library called as ghostscript. The full source code of application will be below there.

 

Live Demo

 

 

You can find the Live Demo of Compress PDF on my Website freemediatools.com/compresspdf

 

 

Screenshots

 

 

 

 

 

Get Started

 

 

 

In order to get started we need to initialize the following commands

 

npm init -y

 

This will create the package.json file for your node.js project

And then you need to install the following dependencies inside your node.js project

 

npm i express

 

npm i multer

 

npm i ejs

 

npm i nodemon

 

After installing all these dependencies we need to make a index.js file and copy paste the following code

 

index.js

 

const express = require("express")

const app = express()

app.listen(5000,() => {

console.log("App is listening on Port 5000")

})

 

 

So in this block of code we are starting a simple express app at port 5000. For this we are including the express library to create a simple http server.

When you execute this app by running the command

 

node index.js

 

You will see your node.js application will start on port 5000

 

 

 

Uploading PDF File For Compression

 

 

 

Now we will be uploading the PDF File from the user so first of all we should have some sort of ui to present to the user so that it can upload the file.

Now we need to set the view engine of our express app to ejs Just write this line inside index.js file as shown below.

 

app.set("view engine","ejs")

 

Now create a simple get request inside the index.js file as shown below.

 

app.get('/compresspdf',(req,res) => {
    res.render('compresspdf',{title:'FREE PDF File Compressor Tool to Compress PDF Online to Smaller Size 100% Works - FreeMediaTools.com'})
  })

 

 

After this Just make a views folder inside the root directory of your project and inside that make a file called as compresspdf.ejs and copy paste the following code which is shown below

 

 

views/compresspdf.ejs

 

 

<!DOCTYPE html>
<html>
  <head>
    <title><%=title%></title>
    <link
      rel="stylesheet"      href="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/css/bootstrap.min.css"
    />
  </head>
  <body>
      <div class="container">
          <h1 class="text-center">
              Compress PDF Online
          </h1>
          <form id="form">
            <div class="form-group">
                <label for="file">Upload PDF File:</label>
                <input class="form-control" type="file" accept=".pdf" name="file" id="upload-input" required>
            </div>
            <div class="progress">
              <div class="progress-bar" role="progressbar"></div>
            </div>
            <div class="form-group">
                <button id="button" class="btn btn-block btn-danger">
                    Compress PDF
                </button>
            </div>
        </form>
        <br><br>
      </div>
</body>
<script src="https://cdnjs.cloudflare.com/ajax/libs/bootstrap-slider/10.0.0/bootstrap-slider.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/sweetalert2@10"></script>
<script>
   // Basic Slider
   var slider = new Slider("#basic", {
        tooltip: 'always'
      });
</script>
  <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.4.1/jquery.min.js"></script>
  <script>
    var files
      $('#form').on('submit', function (e){
        e.preventDefault()
    //$('#upload-input').click();
    $('.progress-bar').text('0%');
    $("#button").text("Uploading File")
    $("#button").prop("disabled","true")
    $('.progress-bar').width('0%');
    convertFile()
});
$('#upload-input').on('change', function(){
  files = $(this).get(0).files;
  var fileExtension = ['pdf'];
        if ($.inArray($(this).val().split('.').pop().toLowerCase(), fileExtension) == -1) {
           $(this).val("") 
    
swal ( "Oops" ,"Please Upload a PDF File",  "error" )

        }
})

function convertFile(){
  if (files.length > 0){
    // create a FormData object which will be sent as the data payload in the
    // AJAX request
    var formData = new FormData();
    // loop through all the selected files and add them to the formData object
    for (var i = 0; i < files.length; i++) {
      var file = files[i];
      // add the files to formData object for the data payload
      formData.append('file', file, file.name);
    }
    console.log(formData)
    var formdata2 = new FormData()
    $.ajax({
      url: '/uploadcompresspdf',
      type: 'POST',
      data: formData,
      processData: false,
      contentType: false,
      success: function(data){
          var data2 = {path:data.path}
          console.log('upload successful!\n' + data.path);
          $("#button").text("File Uploaded Now Processing")
          $("#button").prop("disabled",true);
          formdata2.append('path',data.path)
          $.ajax({
              url:'/compresspdf',
              type:'POST',
              data:JSON.stringify(data2),
              contentType: "application/json",
              dataType:"json",
      success:function(data){

          window.open('/download?path='+data.path)
          $("#button").text("Upload File")
          $("#button").prop("disabled",false);
          location.reload();
      }
          })
      },
      xhr: function() {
        // create an XMLHttpRequest
        var xhr = new XMLHttpRequest();
        // listen to the 'progress' event
        xhr.upload.addEventListener('progress', function(evt) {
          if (evt.lengthComputable) {
            // calculate the percentage of upload completed
            var percentComplete = evt.loaded / evt.total;
            percentComplete = parseInt(percentComplete * 100);
            // update the Bootstrap progress bar with the new percentage
            $('.progress-bar').text(percentComplete + '%');
            $('.progress-bar').width(percentComplete + '%');
            // once the upload reaches 100%, set the progress bar text to done
            if (percentComplete === 100) {
              $('.progress-bar').html('Done');
            }
          }
        }, false);
        return xhr;
      }
    });
  }
}
  </script>
</html>

 

See also  Build a CloudPDF PDF Viewer or Reader in React.js,Angular,Vue.js and Vanilla Javascript Full Project For Beginners

 

Now go again inside the index.js file and make a POST to handle the uploading of the pdf file when the user uploads the pdf file and click the upload button

 

app.post('/uploadcompresspdf',(req,res) => {
  compresspdfupload(req,res,function(err){
    if(err){
      return res.end("Error uploading file")
    }
  })
  res.json({
    path:req.file.path
  })
})

 

 

Now we need to make this middleware function which we are using compresspdfupload in order to upload pdf files on the server using multer

 

So first of all we will include multer inside our application like this at the very top of index.js file

 

var multer = require("multer")

 

 

Now we need to make the multer storage object where we will define on which directory we will store the uploaded files and which filename will be used. Before this we need to create the directory called as public inside the root of the application

 

public/uploads

 

Inside the public directory create another directory called as uploads which will actually store the files for us

 

Now we need to set this public directory as static in express. This is very important to tell express it is static directory.

Copy this line of code inside index.js to tell express

 

app.use(express.static("public"))

 

 

Now we will create the multer storage object like this

 

var storage = multer.diskStorage({
  destination: function (req, file, cb) {
    cb(null, "public/uploads");
  },
  filename: function (req, file, cb) {
    cb(
      null,
      file.fieldname + "-" + Date.now() + path.extname(file.originalname)
    );
  },
});

 

 

And after this we will write the multer file filter which will only allow pdf files to upload as we are working only with pdf files. Copy paste the following code inside index.js

 

const pdfFilter = function (req, file, callback) {
  var ext = path.extname(file.originalname);
  if (ext !== ".pdf") {
    return callback("This Extension is not supported");
  }
  callback(null, true);
};

 

See also  Build a Animated Material Gradient Button with Hover Effect in Browser Using HTML5 and CSS3 Full Project For Beginners

 

Now After this we need to create the actual multer instance passing the storage and filter like this

 

var compresspdfupload= multer({
  storage: storage,
  fileFilter: pdfFilter,
}).single("file");

 

 

As you can see we are only uploading one file at a time so we are using the single method to upload only single file at a time.

 

Now if you run the app it will successfully upload the pdf  file with the progressbar

 

Now we need to write another post request to actually compress the pdf file like this

 

For this purpose we are using a open source library called as ghostscript you can go to their official website to download the software and then you can compress pdf files on the go from the command line.

And now we will be using a special module in node.js to execute shell commands in node.js. The module name is child_process. So we need to include this in index.js

 

const { exec } = require("child_process");

 

 

Inside this child_process module there is a method called as exec which executes shell commands programmatically in node.js

 

Now there is a command in ghostscript which is used to compress pdf files. The command is shown below.

 

gs \ -q -dNOPAUSE -dBATCH -dSAFER \ -sDEVICE=pdfwrite \ -dCompatibilityLevel=1.3 \ -dPDFSETTINGS=/ebook \ -dEmbedAllFonts=true \ -dSubsetFonts=true \ -dAutoRotatePages=/None \ -dColorImageDownsampleType=/Bicubic \ -dColorImageResolution=72 \ -dGrayImageDownsampleType=/Bicubic \ -dGrayImageResolution=72 \ -dMonoImageDownsampleType=/Subsample \ -dMonoImageResolution=72 \ -sOutputFile=${outputFilePath} \ ${inputFile}

 

 

So here you will replace the inputfile and outputfile paths respectively.

 

Now just copy paste the following code inside index.js to execute the above command using exec in node.js

 

 

app.post('/compresspdf',(req,res) => {
  
    var inputFile = req.body.path
    
  
    outputFilePath = Date.now() + "output" + path.extname(req.body.path);
    console.log(outputFilePath);
  
    exec(
      `gs \ -q -dNOPAUSE -dBATCH -dSAFER \ -sDEVICE=pdfwrite \ -dCompatibilityLevel=1.3 \ -dPDFSETTINGS=/ebook \ -dEmbedAllFonts=true \ -dSubsetFonts=true \ -dAutoRotatePages=/None \ -dColorImageDownsampleType=/Bicubic \ -dColorImageResolution=72 \ -dGrayImageDownsampleType=/Bicubic \ -dGrayImageResolution=72 \ -dMonoImageDownsampleType=/Subsample \ -dMonoImageResolution=72 \ -sOutputFile=${outputFilePath} \ ${inputFile}`,
      (err, stdout, stderr) => {
        if (err) {
          res.json({
            error: "some error takes place",
          });
        }
        res.json({
          path: outputFilePath,
        });
      }
    );
  });

 

 

So now at last we need to make a get request to simply download the file once the conversion completes. So below just write this block of code to do this

 

var fs = require("fs")

var path = require("path")


app.get("/download", (req, res) => {
  var pathoutput = req.query.path;
  console.log(pathoutput);
  var fullpath = path.join(__dirname, pathoutput);
  res.download(fullpath, (err) => {
    if (err) {
      fs.unlinkSync(fullpath);
      res.send(err);
    }
    fs.unlinkSync(fullpath);
  });
});

 

 

So here we are using two dependencies extra which are built in node.js which are fs and path modules. Just include it at the very top of the file.

 

 

Full Source Code (Index.js File)

 

 

index.js

 

 

const express = require("express");

const bodyParser = require("body-parser");

const fs = require("fs");

const { exec } = require("child_process");

const path = require("path");

var outputFilePath;

const multer = require("multer");

const app = express();

app.set("view engine","ejs")

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

const PORT = process.env.PORT || 5000;

app.use(express.static("public"));


var storage = multer.diskStorage({
  destination: function (req, file, cb) {
    cb(null, "public/uploads");
  },
  filename: function (req, file, cb) {
    cb(
      null,
      file.fieldname + "-" + Date.now() + path.extname(file.originalname)
    );
  },
});

const pdfFilter = function (req, file, callback) {
  var ext = path.extname(file.originalname);
  if (ext !== ".pdf") {
    return callback("This Extension is not supported");
  }
  callback(null, true);
};

var compresspdfupload = multer({
  storage: storage,
  fileFilter: pdfFilter,
}).single("file");

app.post('/compresspdf',(req,res) => {
  
    var inputFile = req.body.path
    
  
    outputFilePath = Date.now() + "output" + path.extname(req.body.path);
    console.log(outputFilePath);
  
    exec(
      `gs \ -q -dNOPAUSE -dBATCH -dSAFER \ -sDEVICE=pdfwrite \ -dCompatibilityLevel=1.3 \ -dPDFSETTINGS=/ebook \ -dEmbedAllFonts=true \ -dSubsetFonts=true \ -dAutoRotatePages=/None \ -dColorImageDownsampleType=/Bicubic \ -dColorImageResolution=72 \ -dGrayImageDownsampleType=/Bicubic \ -dGrayImageResolution=72 \ -dMonoImageDownsampleType=/Subsample \ -dMonoImageResolution=72 \ -sOutputFile=${outputFilePath} \ ${inputFile}`,
      (err, stdout, stderr) => {
        if (err) {
          res.json({
            error: "some error takes place",
          });
        }
        res.json({
          path: outputFilePath,
        });
      }
    );
  });

  app.get('/compresspdf',(req,res) => {
    res.render('compresspdf',{title:'FREE PDF File Compressor Tool to Compress PDF Online to Smaller Size 100% Works - FreeMediaTools.com'})
  })

app.post('/uploadcompresspdf',(req,res) => {
  compresspdfupload(req,res,function(err){
    if(err){
      return res.end("Error uploading file")
    }
  })
  res.json({
    path:req.file.path
  })
})

app.get("/download", (req, res) => {
  var pathoutput = req.query.path;
  console.log(pathoutput);
  var fullpath = path.join(__dirname, pathoutput);
  res.download(fullpath, (err) => {
    if (err) {
      fs.unlinkSync(fullpath);
      res.send(err);
    }
    fs.unlinkSync(fullpath);
  });
});

app.listen(PORT, () => {
  console.log(`App is listening on Port ${PORT}`);
});

 

See also  Javascript Tutorial to Read and Display Contents of File in Browser When Uploaded Using FileReader Class Full Project For Beginners

 

 

 

Leave a Reply