Upload and Resize Multiple Images in Node.js using Express, Multer, Sharp

To upload and resize an image to the node express server, use the “sharp library”. We will build Web APIs through an express web framework very quickly, and it has tremendous support for the NoSQL databases like MongoDB.

Here is the step-by-step guide:

Step 1: Create Node Express Project

Create a project folder by the following command.

mkdir nodeimageupload

cd nodeimageupload

Now, create a package.json file using the following command.

npm init -y

Next, install express as a framework,ejs as a template engine, body-parser, multer as a  node.js middleware for handling multipart/form-data, uuid for getting the random name, and sharp as an image resize libraries using NPM.

npm install express body-parser ejs uuid multer sharp --save

Also, install the nodemon server as a development dependency.

npm install nodemon --save-dev

Now, open the project in Visual Studio Code.

Change the package.json file and add the following line in the “script”.

"scripts": {
   "start": "nodemon server.js"
},

Step 2: Create a server.js file

Create one file in the project root called the server.js and add the following code.

// server.js

const express = require('express');
const app = express();
const port = process.env.PORT || 3000;

app.listen(port, function () {
  console.log('Server is running on PORT',port);
});

Go to the terminal and start the node server with the following command.

npm start

Starting the npm server

So, our nodemon development server is up and running.

Step 3: Configure the EJS templating engine.

To include the CSS and JS files in the express, create a static directory called public in the root, and in that, we will put our CSS and JS files. So, create the first public directory.

Add the following code inside the server.js file.

// server.js

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

The next step is to set up the ejs template engine. Add the following code inside the server.js file.

// server.js

app.set('view engine', 'ejs');

We need to create one folder inside our root called views. Then, in that folder, make one file called index.ejs.

<!-- index.ejs -->

<!DOCTYPE html>
<html>
 <head>
 <meta charset="utf-8">
 <title>EJS Engine</title>
 </head>
 <body>
 <p>Node Express Image Upload and Resize Example</p>
 </body>
</html>

Also, create an index.html file inside the public folder.

<!-- index.html -->

<!DOCTYPE html>
<html lang="en">
<head>
 <meta charset="UTF-8">
 <meta name="viewport" content="width=He, initial-scale=1.0">
 <meta http-equiv="X-UA-Compatible" content="ie=edge">
 <title>Node Express Image Upload Example</title>
</head>
<body>
 <p>
 Node Express Image Upload and Resize Example
 </p>
</body>
</html>

Step 4: Configure Express Router

Set up the routes for our application. So use the Router module provided by Express js. So, create a file in the root folder called router.js.

Now, write the following code inside the router.js file.

// router.js

const express = require('express');
const app = express();
const router = express.Router();

router.get('/', async function (req, res) {
 await res.render('index');
});
module.exports = router;

Now in the server.js filewe need to require the router.js file.

// server.js

const express = require('express');
const bodyParser = require('body-parser');

const app = express();
const port = process.env.PORT || 3000;
const router = require('./router');

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

app.use(express.static('public'));
app.set('view engine', 'ejs');

app.use('/upload', router);

app.listen(port, function () {
 console.log('Server is running on PORT',port);
});

Now, go to the browser and hit this URL: http://localhost:3000/upload. You can see the basic HTML view.

Step 5: Create a form

Inside the index.ejs file must create one HTML form to upload the image.

<!DOCTYPE html>
<html>
 <head>
 <meta charset="utf-8">
 <title>EJS Engine</title>
 </head>
 <body>
 <p>Image Upload</p>
 <form method="post" action="upload/post" enctype="multipart/form-data">
 <input type="file" name="image" /><br /><br />
 <button type="submit" name="upload">Upload</button>
 </form>
 </body>
</html>

Now, go to http://localhost:3000/upload and see the underlying HTML form to upload an image.

Step 6: Create file upload middleware

To handle the multipart/form-data in Node.js, we have already installed the multer library. So let’s create a middleware inside the project’s root called uploadMiddleware.js.

// uploadMiddleware.js

const multer = require('multer');

const upload = multer({
  limits: {
    fileSize: 4 * 1024 * 1024,
  }
});

module.exports = upload

Now, import this middleware inside the router.js file to handle the POST request.

// router.js

const express = require('express');
const app = express();
const router = express.Router();
const upload = require('./uploadMiddleware');

router.get('/', async function (req, res) {
 await res.render('index');
});

router.post('/post', upload.single('image'), async function (req, res) {
 await console.log('post');
});

module.exports = router;

Here, we have used the node async-await feature. 

So, when the user tries to upload an image to the server, the router. Post function will be executed, and a post will be printed in the console. That means we must resize the image and save it in the file directory.

Step 7: Resize the image

For resizing the image in Node.js and achieving High-performance Node.js image processing, Sharp is  the fastest module to resize JPEG, PNG, WebP, and TIFF images. We have already installed the sharp. Now, create a file inside the root called Resize.js and add the following code.

// Resize.js

const sharp = require('sharp');
const uuidv4 = require('uuid/v4');
const path = require('path');

class Resize {
 constructor(folder) {
 this.folder = folder;
 }
 async save(buffer) {
 const filename = Resize.filename();
 const filepath = this.filepath(filename);

 await sharp(buffer)
 .resize(300, 300, {
 fit: sharp.fit.inside,
 withoutEnlargement: true
 })
 .toFile(filepath);
 
 return filename;
 }
 static filename() {
 return `${uuidv4()}.png`;
 }
 filepath(filename) {
 return path.resolve(`${this.folder}/${filename}`)
 }
}
module.exports = Resize;

So, in the above file, we have created a class called Resize.js which accepts one argument: folder path up to the images folder. Now, you need to create the images folder inside the public directory.

Then, we defined the static function filename, which returns the filename’s random string and then defined the filepath function, which returns the complete filepath of the uploaded image.

Then we defined the save() function, which accepts the file buffer from the user request, resizes that image,d uploads it to that filepath, and returns the filename to the User.

Now, import the Resize.js file inside the router.js file.

Step 8: Save the image in the file system

We need to import the Resize.js file inside the router.js file because we handle the post request there. So, write the following code inside the router.js file.

// router.js

const express = require('express');
const app = express();
const path = require('path');

const router = express.Router();
const upload = require('./uploadMiddleware');
const Resize = require('./Resize');

router.get('/', async function (req, res) {
  await res.render('index');
});

router.post('/post', upload.single('image'), async function (req, res) {
  const imagePath = path.join(__dirname, '/public/images');
  const fileUpload = new Resize(imagePath);
  if (!req.file) {
    res.status(401).json({error: 'Please provide an image'});
  }
  const filename = await fileUpload.save(req.file.buffer);
  return res.status(200).json({ name: filename });
});

module.exports = router;

First, inside the router.post request, we have defined the upload folder and then passed that folder to the constructor of Resize class. It will return the object, and then we call the save() method on that object, give the image buffer as an argument to the save() function, and return the file name, and we are, for now, just displaying the filename in JSON format to the User.

If the file is not there, we display an error message to the user in JSON format.

Step 9: Run the Project.

Now, if you try to upload an image, you will see the output in the browser like the below image.

JSON response of an image

So, we have got the correct JSON response. Now, go to the file system, and inside the public >> images folder, you can see the randomly named image.

That’s it.

Github Code

3 thoughts on “Upload and Resize Multiple Images in Node.js using Express, Multer, Sharp”

  1. Dear Krunal,
    up to step 4 all things are working fine. After modifying server.js with the rooter path I get Error message “Cannot find module ‘./router’ “. In your description you write “So, create a file in the root folder called router.js. ” That might be wrong. Could you please correct it. The tutorial is good to understand. In this case I would apritiate to continue.
    Thanks in advance
    Ulrich

    Reply

Leave a Comment

This site uses Akismet to reduce spam. Learn how your comment data is processed.