Skip to main content

File Upload with Multer in Node.js and Express

File upload is a common operation for any applications. In Node.js, with the Express web framework and the Multer library, adding file upload feature to your app is very easy. In this tutorial, we are going to learn how to upload files on the server with the help of Multer and Express in Node.js. The goal is to make you comfortable in building apps that can easily handle any file uploads. At the end of this blog, you will be able to integrate the file uploads in your own apps.
We will be covering the following topics:
  • What is Multer?
  • Project Setup
  • Install the dependencies
  • Testing Our API Using Postman
  • Adding Multer
  • DiskStorage
  • Other Options in Upload
  • Uploading Multiple Files

What is Multer?

Multer is a node.js middleware for handling multipart/form-data, which is primarily used for uploading files. It is written on top of the busyboy, for maximum efficiencyBy this, you can understand that multer is used to handle multipart/form-data.
What is Multipart Data?
In general, when a “form” is submitted, browsers use “application-xx-www-form-urlencoded” content-type. This type contains only a list of keys and values and therefore are not capable of uploading files. Whereas, when you configure your form to use “multipart/form-data” content-type, browsers will create a “multipart” message where each part will contain a field of the form. A multipart message will consist of text input and file input. This way using multipart/form-data you can upload files.
Multer adds a body object and a file or files object to the request object. The body object contains the values of the text fields of the form, the file or files object contains the files uploaded via the form.
Multer will not process any form which is not multipart (multipart/form-data).

Project Setup

Create a directory for the project and give it any name. We will call it MulterApp. 
Now, let’s start by first defining the package.json file to store our app’s configuration. To create one, navigate to the MulterApp directory in terminal, and write the following command:
// In command prompt or terminal
npm init
Answer a few questions (app name, git repo, etc…) and you’ll be ready to roll.

Install the dependencies

Here, the only two dependencies are express and multer. So we will install it one by one via npm(Node Package Manager).
// installing express module 
npm install express --save
We are now ready to write some code. Create a file with any name of your choice, we will call it app.js. Load the express module using require() method and then set up a basic express server by writing the following code in app.js.
// load express
const express = require('express');
const app = express();
app.get(‘/’, (req, res) => {  
   res.send(‘hello world’);
});
app.listen(3000, () => { 
    console.log('Started on port 3000');
});
Now run the code by writing the following command in the terminal:
node app.js
After this, open the browser and type http://localhost:3000.
You should see “Hello World” printing to the document window. We have set up the basic server.

Testing Our API Using Postman

Postman is an essential and fantastic tool if you are building rest API. We will use Postman to test our routes. As we are not using any form tag or frontend therefore we will make requests and specify our form data from Postman only. So, make sure that you have Postman installed. Now let's add multer to our project.

Adding Multer

Before using multer, we have to install it using npm.
// installing multer module  
npm install multer --save
In this project, we will store the uploaded files in a folder for simplicity. Usually we store the files in the Amazon S3 bucket.
We will now load multer in the app.js file using the require() method. The following code will go in the app.js file.
const multer = require('multer');
const upload = multer({dest:'uploads/'}).single("demo_image");
Here, we have called the multer() method. It accepts an options object, with destproperty, which tells Multer where to upload the files. If you omit this object, the files will be kept in memory and never written to disk.
Once this is done, We will now create our post route. We will make a POST request to the URL [localhost:port/image]. For that, we will first have to listen to that endpoint and we will do that by using the post()method.
Here we are making a post request because, in the actual scenario also, It will be a post request only, as the form tag will going to post this data to a specific URL(by specifying method=”POST” and action=”/image” in form tag).
The following code will go in app.js:
app.post("/image", (req, res) => {
   upload(req, res, (err) => {
    if(err) {
      res.status(400).send("Something went wrong!");
    }
    res.send(req.file);
  });
});

Multer supports uploading a single file as well as multiple files. In this case, we have used multer({..}).single() which is used for uploading a single file. As I have mentioned before that the multer adds a file object to the request. The file object contains metadata related to the file.
Now we will be using Postman to test this endpoint.
Here note that the key name or the field name that you are providing in form data should be the same as the one provided in the multer({..}).single() (here name is demo_image).
Now see your file structure again, notice that uploads folder is created in the location provided in dest option(in our case in the project directory). If you want more controls over the uploads we will use the storage option instead of dest.

DiskStorage

The disk storage engine gives you full control over storing files to disk. We will create a storage object using the diskStorage() method.
The following code will go in app.js:
var storage = multer.diskStorage({   
   destination: function(req, file, cb) { 
      cb(null, './uploads');    
   }, 
   filename: function (req, file, cb) { 
      cb(null , file.originalname);   
   }
});
Here, there are two properties, destination, and filename. They both are functions.
destination - It can also be given as a string (e.g. './uploads'). If no destination is given, the operating system's default directory for temporary files is used. It is mandatory to create a directory when you are using destination as a function. Otherwise, if you are using destination as a string, multer will make sure that the directory is created for you.
filename - It is used to determine what the file should be named inside the folder. If you don't provide any filename, each file will be given a random name without any file extension. It is your responsibility to provide a function that should return a complete filename with a file extension. Both these functions take 3 arguments - the request object, the file object and a callback function (here, cb is callback function). The 2 arguments to cb are:
  • null - as we don’t want to show any error.
  • file.originalname - here, we have used the same name of the file as they were uploaded. You can use any name of your choice.
Now let’s modify the variable a little bit.
// In app.js 
var upload = multer({ storage: storage }).single("demo_image");
Again test this in Postman. You will find the same output but now check the image in the uploads folder. You will find the same filename as you uploaded, with the proper extension.

Other Options in Upload

  1. limits - You can also put a limit on the size of the file that is being uploaded with the help of using limits.
The following code will go inside the multer().
// inside multer({}), file upto only 1MB can be uploaded
const upload = multer({
       storage: storage,
       limits : {fileSize : 1000000}
});
Here, fileSize is in bytes. (1000000 bytes = 1MB)
2. fileFilter - Set this to a function to control which files should be uploaded and which should be skipped. The function should look like this:
// this code goes inside the object passed to multer()
function fileFilter (req, file, cb) {  
   // The function should call `cb` with a boolean  
   // to indicate if the file should be accepted  

   // To reject this file pass `false`, like so:   
   cb(null, false);
   // To accept the file pass `true`, like so:   
   cb(null, true);   
   // You can always pass an error if something goes wrong:   
   cb(new Error('I don\'t have a clue!')); 
}
For Example, if we only want the user to upload the image file (jpeg, jpg, png, gif).
Then the code will look like this and will go in app.js:
// this code goes inside the object passed to multer()
function fileFilter (req, file, cb) {    
  // Allowed ext
   const filetypes = /jpeg|jpg|png|gif/;

 // Check ext
  const extname =  filetypes.test(path.extname(file.originalname).toLowerCase());
 // Check mime
 const mimetype = filetypes.test(file.mimetype);

 if(mimetype && extname){
     return cb(null,true);
 } else {
     cb('Error: Images Only!');
 }
}

Uploading Multiple Files

We can upload multiple files as well. In this case, multer gives us another function called .arrays(fieldname[, max_count]) that accepts an array of files, all with the name fieldname. It generates an error if more than max_count files are uploaded. The array of files will be stored in req.files.
The following code will go in app.js
// uploading multiple images together
app.post("/images", upload.array("demo_images", 4), (req, res) =>{
  try {
    res.send(req.files);
  } catch (error) {
    console.log(error);
    res.send(400);
  }
});
Go to Postman, enter the specified URL, select multiple files and then press Enter.

Closing Notes

Now, we know how to integrate file uploads using multer in any application. Go ahead! make your own application with complete frontend and integrate the file uploads by using the above-acquired knowledge.

Comments

Popular posts from this blog

How to use Ngx-Charts in Angular ?

Charts helps us to visualize large amount of data in an easy to understand and interactive way. This helps businesses to grow more by taking important decisions from the data. For example, e-commerce can have charts or reports for product sales, with various categories like product type, year, etc. In angular, we have various charting libraries to create charts.  Ngx-charts  is one of them. Check out the list of  best angular chart libraries .  In this article, we will see data visualization with ngx-charts and how to use ngx-charts in angular application ? We will see, How to install ngx-charts in angular ? Create a vertical bar chart Create a pie chart, advanced pie chart and pie chart grid Introduction ngx-charts  is an open-source and declarative charting framework for angular2+. It is maintained by  Swimlane . It is using Angular to render and animate the SVG elements with all of its binding and speed goodness and uses d3 for the excellent math functio...

Understand Angular’s forRoot and forChild

  forRoot   /   forChild   is a pattern for singleton services that most of us know from routing. Routing is actually the main use case for it and as it is not commonly used outside of it, I wouldn’t be surprised if most Angular developers haven’t given it a second thought. However, as the official Angular documentation puts it: “Understanding how  forRoot()  works to make sure a service is a singleton will inform your development at a deeper level.” So let’s go. Providers & Injectors Angular comes with a dependency injection (DI) mechanism. When a component depends on a service, you don’t manually create an instance of the service. You  inject  the service and the dependency injection system takes care of providing an instance. import { Component, OnInit } from '@angular/core'; import { TestService } from 'src/app/services/test.service'; @Component({ selector: 'app-test', templateUrl: './test.component.html', styleUrls: ['./test.compon...

How to solve Puppeteer TimeoutError: Navigation timeout of 30000 ms exceeded

During the automation of multiple tasks on my job and personal projects, i decided to move on  Puppeteer  instead of the old school PhantomJS. One of the most usual problems with pages that contain a lot of content, because of the ads, images etc. is the load time, an exception is thrown (specifically the TimeoutError) after a page takes more than 30000ms (30 seconds) to load totally. To solve this problem, you will have 2 options, either to increase this timeout in the configuration or remove it at all. Personally, i prefer to remove the limit as i know that the pages that i work with will end up loading someday. In this article, i'll explain you briefly 2 ways to bypass this limitation. A. Globally on the tab The option that i prefer, as i browse multiple pages in the same tab, is to remove the timeout limit on the tab that i use to browse. For example, to remove the limit you should add: await page . setDefaultNavigationTimeout ( 0 ) ;  COPY SNIPPET The setDefaultNav...