Node Express Image Upload and Resize Guide

Node.js as a platform and express as a lightweight framework is the best choice for backend development. You can find the tutorial about Node Express MongoDB tutorial on this blog.

Node express image upload and resize

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.

Okay, now let’s go to the project.

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, 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);
});

Now, go to the terminal and start the node server by the following command.

npm start

Node Express Image Upload and Resize Tutorial Example

So, our nodemon development server is up and running.

Step 3: Configure the EJS templating engine.

For including the css and js files in the express, first, we will 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, we need to create one HTML form to upload the image.

// index.ejs

<!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

Okay, 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 now we need to resize the image and then 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, the fastest module to resize JPEG, PNG, WebP, and TIFF images is Sharp. 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 and accepts one argument: folder path up to images folder. Now, you need to create the images folder inside the public directory.

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

Then we have defined the save() function, which accepts the file buffer coming from the user request and then resize that image and upload to that filepath and return 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.

Upload and Resize the 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 the Node Express Image Upload and Resize example. Thanks for taking it, and also, see the Github code if you find any errors.

Github Code