πŸ“–
Maissen's Grimoire
  • Maissen's Grimoire
  • Html and css grimoire
    • HTML5 Periodical Table
    • HTML Cheat Sheet
    • CSS Cheatsheets
  • Javascript Grimoire
    • JavaScript Cheat Sheet
      • Javascript Array in depth
      • Tagged Template Literals
      • Guard Clauses - The Best Way To Write Complex Conditional Logic
      • JavaScript Optional Chaining
      • JavaScript Null Coalesce
      • What Are Magic Numbers And Why Are They Bad
      • ES6/ECMAScript2015 Cheatsheet
      • First-class and Higher Order Functions: Effective Functional JavaScript
    • Useful JavaScript Tips, Tricks and Best Practices
    • Bits of code
    • Useful JavaScript libraries
      • Components
      • Animation
      • Maps
      • Helpers
      • Presentations
      • Charts
      • Games
      • Audio
      • Images
      • Video
    • Js the right way
  • Angular Grimoire
    • Angular doc
    • Getting Started
    • Angular clean architecture
    • Angular Cheat Sheet
    • TypeScript Cheat Sheet
    • My Favorite Tips and Tricks in Angular
    • NgRx: tips & tricks
    • Bits of code
      • Execute Multiple HTTP Requests in Angular
      • Authentification
        • Angular 8 JWT Authentication with HttpInterceptor and Router
      • Integrations
        • Spring Boot
          • Rest Example
            • Angular,Spring Boot,Spring Data and Rest Example(CRUD)
          • Authentification
            • Angular, Spring Boot: JWT Authentication with Spring Security example
            • Angular Spring Boot Security Oauth2
              • Spring Boot OAUTH2 Role-Based Authorization
              • Spring Boot Security Google Oauth
              • Spring Security OAuth2 User Registration
    • Most used dependency
  • Node Grimoire
    • Express.js 4 Cheatsheet
    • Useful Dependencies
    • How To Use And Write Express Middleware
    • Node.js with SQL databases
      • Node.js Token Based Authentication & Authorization example
      • Node.js Rest APIs example with Express, Sequelize & MySQL
      • Node.js Express & PostgreSQL: CRUD Rest APIs example with Sequelize
      • Sequelize
        • Sequelize Many-to-Many Association example – Node.js & MySQL
        • Sequelize One-to-Many Association example with Node.js & MySQL
    • Node.js with NOSQL databases
      • Node.js + MongoDB: User Authentication & Authorization with JWT
      • Node.js, Express & MongoDb: Build a CRUD Rest Api example
      • MongoDB One-to-One relationship tutorial with Mongoose example
      • MongoDB One-to-Many Relationship tutorial with Mongoose examples
      • MongoDB Many-to-Many Relationship with Mongoose examples
  • Upload files
    • How to upload multiple files in Node.js
    • Upload & resize multiple images in Node.js using Express, Multer, Sharp
    • Upload/store images in MySQL using Node.js, Express & Multer
    • How to upload/store images in MongoDB using Node.js, Express & Multer
  • React Grimoire
    • React Doc
    • React Grimoire
    • React Cheat Sheet
  • spring boot Grimoire
    • Getting started
    • Spring Boot, Spring Data JPA – Rest CRUD API example
    • Spring Boot Token based Authentication with Spring Security & JWT
  • Mongo Grimoire
    • MongoDb-Mongoose Cheat Sheet
  • Development tools
    • Design Patterns
  • maissen_grimoire
Powered by GitBook
On this page
  • Uploading multiple images using Multer
  • Resizing images using Sharp
  • The Route Handler Functions
  • Demo
  • Practice: Upload & Resize multiple images with Node.js

Was this helpful?

  1. Upload files

Upload & resize multiple images in Node.js using Express, Multer, Sharp

Uploading multiple images using Multer

Upload multiple images View

In HTML, we create a form with following elements:

  • action="/multiple-upload"

  • enctype="multipart/form-data"

  • multiple input

<form
  action="/multiple-upload"
  method="POST"
  enctype="multipart/form-data">
    ...
    <input type="file" multiple>
    ...
</form>

Using Multer to upload multiple Images

Let’s configure multer and create some functions.

const multer = require("multer");

const multerStorage = multer.memoryStorage();

const multerFilter = (req, file, cb) => {
  if (file.mimetype.startsWith("image")) {
    cb(null, true);
  } else {
    cb("Please upload only images.", false);
  }
};

const upload = multer({
  storage: multerStorage,
  fileFilter: multerFilter
});

const uploadFiles = upload.array("images", 10); // limit to 10 images

const uploadImages = (req, res, next) => {
  uploadFiles(req, res, err => {
    if (err instanceof multer.MulterError) { // A Multer error occurred when uploading.
      if (err.code === "LIMIT_UNEXPECTED_FILE") { // Too many images exceeding the allowed limit
        // ...
      }
    } else if (err) {
      // handle other errors
    }

    // Everything is ok.
    next();
  });
};

In the code above, we’ve done these steps: – First, import multer module. – Next, configure multer to store images in memory as a buffer so that we could then use it later by other processes (resize the images before saving them to disk). – We also define a filter to only allow images to pass. – Then use multer object to create uploadFiles function with the field images and the max count. The array of files will be stored in req.files. – We catch errors by calling the uploadFiles middleware function, if there is no error, call next().

Resizing images using Sharp

Now we’re gonna process all of uploaded images (which are in memory).

const sharp = require("sharp");

const resizeImages = async (req, res, next) => {
  if (!req.files) return next();

  req.body.images = [];
  await Promise.all(
    req.files.map(async file => {
      const newFilename = ...;

      await sharp(file.buffer)
        .resize(640, 320)
        .toFormat("jpeg")
        .jpeg({ quality: 90 })
        .toFile(`upload/${newFilename}`);

      req.body.images.push(newFilename);
    })
  );

  next();
};

Let me explain the code. – We import sharp module. – The resizeImages will be an async function in that:

  • We check if there are no images uploaded, move straight to the next middleware

  • For each image, we return a Promise, we need all of the Promises done before calling next(). So we get an array of all of these Promises using array.map() then put it in Promise.all() function.

The Route Handler Functions

We write all middleware functions above in a Controller called upload. We use Express Router to handle POST action to "/multiple-upload" endpoint.

const express = require("express");
const router = express.Router();
const uploadController = require("./../controllers/upload");

let routes = app => {
  ...
  router.post(
    "/multiple-upload",
    uploadController.uploadImages,
    uploadController.resizeImages,
    uploadController.getResult
  );

  return app.use("/", router);
};

module.exports = routes;

You can see that we insert uploadImages and resizeImages, then uploadController.getResult. This is because we will process images before showing the result message.

Demo

Open browser for the app:

Choose some images to upload & resize:

Click on Submit button, if the process is successful, browser shows the uploaded images:

Check the upload folder, you can see the resized images:

If you choose the file without image format, or the images you want to upload exceeds the allowed amount, the browser will show the messages.

Practice: Upload & Resize multiple images with Node.js

Now I’m gonna show you how to build this Node.js application step by step.

Project Structure

This is our project structure:

– upload: the folder for storing uploaded images. – views/index.html: contains HTML form for user to upload images. – routes/web.js: defines routes for endpoints that is called from views, use controllers to handle requests. – controllers:

  • home.js returns views/index.html

  • upload.js handles upload & resize multiple images with middleware functions.

– server.js: initializes routes, runs Express app.

Setup Node.js modules

Change current directory to the root folder of our project, then install Express, Multer, Sharp with the following command:

npm install express multer sharp

Create View for uploading multiple images

In views folder, create index.html with the HTML and Javascript code as below:

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <meta http-equiv="X-UA-Compatible" content="ie=edge" />
    <title>Node.js upload & resize multiple files</title>
    <link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/css/bootstrap.min.css" />
    <style>
      div.preview-images > img {
        width: 30%;
      }
    </style>
  </head>
  <body>
    <div class="container">
      <div class="row">
        <div class="col-sm-8 mt-3">
          <h4>Node.js upload & resize multiple files - bezkoder.com</h4>

          <form class="mt-4"
            action="/multiple-upload"
            method="POST"
            enctype="multipart/form-data"
          >
            <input
              type="file"
              name="images"
              multiple
              id="input-images"
              class="form-control-file border"
            />
            <button type="submit" class="btn btn-primary mt-2">Submit</button>
          </form>
        </div>
      </div>
      <hr />
      <div class="row">
        <div class="col-sm-12">
          <div class="preview-images"></div>
        </div>
      </div>
    </div>
    <script src="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/js/bootstrap.bundle.min.js"></script>
    <script src="https://code.jquery.com/jquery-3.4.1.min.js"></script>
    <script>
      $(document).ready(function() {
        let imagesPreview = function(input, placeToInsertImagePreview) {
          if (input.files) {
            let filesAmount = input.files.length;
            for (i = 0; i < filesAmount; i++) {
              let reader = new FileReader();
              reader.onload = function(event) {
                $($.parseHTML("<img>"))
                  .attr("src", event.target.result)
                  .appendTo(placeToInsertImagePreview);
              };
              reader.readAsDataURL(input.files[i]);
            }
          }
        };
        $("#input-images").on("change", function() {
          imagesPreview(this, "div.preview-images");
        });
      });
    </script>
  </body>
</html>

The HTML code is easy to understand, the jQuery script shows preview of the chosen images. We also use Bootstrap to make the UI more comfortable to read.

Create Controller for the view

Under controllers folder, create home.js file.

const path = require("path");

const home = (req, res) => {
  return res.sendFile(path.join(`${__dirname}/../views/index.html`));
};

module.exports = {
  getHome: home
};

Create Controller for processing Images

This is the main code of our Node.js project. The Upload Controller uses both multer & sharp module.

We’re gonna export 3 middleware functions:

  • uploadImages

  • resizeImages

  • getResult

const multer = require("multer");
const sharp = require("sharp");

const multerStorage = multer.memoryStorage();

const multerFilter = (req, file, cb) => {
  if (file.mimetype.startsWith("image")) {
    cb(null, true);
  } else {
    cb("Please upload only images.", false);
  }
};

const upload = multer({
  storage: multerStorage,
  fileFilter: multerFilter
});

const uploadFiles = upload.array("images", 10);

const uploadImages = (req, res, next) => {
  uploadFiles(req, res, err => {
    if (err instanceof multer.MulterError) {
      if (err.code === "LIMIT_UNEXPECTED_FILE") {
        return res.send("Too many files to upload.");
      }
    } else if (err) {
      return res.send(err);
    }

    next();
  });
};

const resizeImages = async (req, res, next) => {
  if (!req.files) return next();

  req.body.images = [];
  await Promise.all(
    req.files.map(async file => {
      const filename = file.originalname.replace(/\..+$/, "");
      const newFilename = `bezkoder-${filename}-${Date.now()}.jpeg`;

      await sharp(file.buffer)
        .resize(640, 320)
        .toFormat("jpeg")
        .jpeg({ quality: 90 })
        .toFile(`upload/${newFilename}`);

      req.body.images.push(newFilename);
    })
  );

  next();
};

const getResult = async (req, res) => {
  if (req.body.images.length <= 0) {
    return res.send(`You must select at least 1 image.`);
  }

  const images = req.body.images
    .map(image => "" + image + "")
    .join("");

  return res.send(`Images were uploaded:${images}`);
};

module.exports = {
  uploadImages: uploadImages,
  resizeImages: resizeImages,
  getResult: getResult
};

In the resizeImages function, we: – get each image name and create new name for it with jpeg extension. – resize to 640x320 – change the image format to jpeg – set the quality to 90% of the original image – save the image file to upload folder

Define routes

We define routes in routes/web.js like this. There are 2 routes: – GET: Home page for the upload form. – POST "/multiple-upload" to use three uploadController functions.

const express = require("express");
const router = express.Router();
const homeController = require("../controllers/home");
const uploadController = require("./../controllers/upload");

let routes = app => {
  router.get("/", homeController.getHome);

  router.post(
    "/multiple-upload",
    uploadController.uploadImages,
    uploadController.resizeImages,
    uploadController.getResult
  );

  return app.use("/", router);
};

module.exports = routes;

Create Express app server

Finally, we only need to create an Express server.

server.js

const express = require("express");
const app = express();
const initRoutes = require("./routes/web");

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

let port = 3000;
app.listen(port, () => {
  console.log(`Running at localhost:${port}`);
});

Run the app

Before running this Node.js app, you must create upload folder in the project root folder.

Run following command: node src/server.js

If everything is ok, the console shows:

Running at localhost:3000

Open browser with url http://localhost:3000/ and you can check the result now.

PreviousHow to upload multiple files in Node.jsNextUpload/store images in MySQL using Node.js, Express & Multer

Last updated 5 years ago

Was this helpful?

We process every image in the images array using method, then change the format (with file extension) to jpeg with and save it to disk using method.

node-js-upload-resize-multiple-images-demo-open-browser
node-js-upload-resize-multiple-images-demo-import-images
node-js-upload-resize-multiple-images-demo-result-successful
node-js-upload-resize-multiple-images-demo-result-successful-folder
node-js-upload-resize-multiple-images-demo-result-failed
node-js-upload-resize-multiple-images-project-structure
resize()
toFormat()
toFile()