Node.js Image Upload, Processing and Resizing using Sharp package
Often in our web applications, we need to store multiple forms and formats of images, in the form of a profile picture or an image for a product in an e-commerce prototype. In most of our cases, we need to store images compressed to multiple sizes, retaining the quality. For example, for a product at an e-commerce site, we would require storing 3 versions of a product image:
- Thumbnail
- Low resolution for previews, etc.
- The original high resolution for the actual product.
Prerequisites:
- Node.js basics
- Routes handling in express.js
Modules used: sharp, Multer
According to the official npm documentation, The typical use case for sharp is to convert large images in common formats to smaller, web-friendly JPEG, PNG, and WebP images of varying dimensions.
Initialize npm in an empty directory to begin with the following command:
npm init -y
Install the required modules with the following command:
npm install express --save npm install body-parser --save npm install sharp --save npm install multer --save
Multer setup:
To upload files, we need to configure multer as a middleware to be passed. To set up multer, we need to add the following code to our application.
Note: For additional usage and to know more about uploads and multer, you can refer to the official documentation at Multer
javascript
// Importing the module const multer = require( 'multer' ); // Setting up a middleware specifying the // destination for storing the images const upload = multer({dest : './images' }) |
Since multer works with form data, you need to ensure the upload is via a form with configuration as multipart/form-data.
Filename: app.js
javascript
const express = require( 'express' ); const bodyparser = require( 'body-parser' ); const fs = require( 'fs' ); const multer = require( 'multer' ); const sharp = require( 'sharp' ); const upload = multer({dest : './images' }) // Initialize the express object const app = express(); // Use body-parser to parse incoming data app.use(bodyparser.urlencoded({extended : true })) // Use the upload middleware containing // our file configuration, with the name // of input file attribute as "avatar" // to the desired configuration. app.post( '/upload' , upload.single( "avatar" ), (req, res)=> { fs.rename(req.file.path, './images/avatar.jpg' , (err)=>{ console.log(err); }) return res.json( "File Uploaded Successfully!" ); }); app.listen(3000, ()=>{ console.log( "Server Running!" ) }) |
Steps to run the above code:
Run the app.js file using the following command:
node app.js
After executing the above command, you will see the following output:
Server Running!
Send a POST request to https://localhost:3000/upload using Postman. You need to pass “avatar” as KEY and picture as VALUE.
After hitting the request, an image directory will be created with our desired image.
Processing Image using Sharp: We will be processing images via a sharp package. To create multiple instances with different properties, we use the following code:
javascript
// Configuring thumbnail image sharp(__dirname + '/images/avatar.jpg' ).resize(200,200) .jpeg({quality : 50}).toFile(__dirname + '/images/avatar_thumb.jpg' ); // Configuring Preview Image sharp(__dirname + '/images/avatar.jpg' ).resize(640,480) .jpeg({quality : 80}).toFile(__dirname + '/images/avatar_preview.jpg' ); |
So all things are set, the final app.js will be as follows:
Filename: app.js
javascript
const express = require( 'express' ); const bodyparser = require( 'body-parser' ); const fs = require( 'fs' ); const multer = require( 'multer' ); const sharp = require( 'sharp' ); const upload = multer({dest : './images' }) const app = express(); app.use(bodyparser.urlencoded({extended : true })) app.post( '/upload' , upload.single( "avatar" ), (req, res)=> { fs.rename(req.file.path, './images/avatar.jpg' , (err)=>{ console.log(err); }) sharp(__dirname + '/images/avatar.jpg' ).resize(200,200) .jpeg({quality : 50}).toFile(__dirname + '/images/avatar_thumb.jpg' ); sharp(__dirname + '/images/avatar.jpg' ).resize(640,480) .jpeg({quality : 80}).toFile(__dirname + '/images/avatar_preview.jpg' ); return res.json( "File Uploaded Successfully!" ); }); app.listen(3000, ()=>{ console.log( "Server Running!" ) }) |
Upon running the server and sending the same request as before, you will get your all uploaded images in the image directory with the desired configuration as shown below:
Additional Sharp Options: https://sharp.pixelplumbing.com/