Processing File Upload with the Express Multer Middleware

John Au-Yeung - Jan 24 '21 - - Dev Community

Check out my books on Amazon at https://www.amazon.com/John-Au-Yeung/e/B08FT5NT62

Subscribe to my email list now at http://jauyeung.net/subscribe/

Multer is a middleware that lets us process file uploads with our Express app.

In this article, we’ll look at how to use it to process uploads and process text data in multipart forms.

How to Use it?

We can install it by running:

npm install --save multer
Enter fullscreen mode Exit fullscreen mode

Once it’s installed we have to make a form that has the encoding type multipart/form-data .

It won’t process any form that’s not multipart, i.e. has the enctype set to multipart/form-data .

Simple Usage

The simplest usage is to allow upload of one file at a time. We can do this by calling the multer function and setting the path to store the uploaded file as follows:

const express = require('express');  
const bodyParser = require('body-parser');  
const multer = require('multer');  
const upload = multer({ dest: './uploads/' });  
const app = express();
app.use(bodyParser.json());  
app.use(bodyParser.urlencoded({ extended: true }));
app.use(express.static('public'));
app.get('/', (req, res) => {  
  res.sendFile('public/index.html');  
});
app.post('/upload', upload.single('upload'), (req, res) => {  
  res.send('file uploaded')  
});
app.listen(3000, () => console.log('server started'));
Enter fullscreen mode Exit fullscreen mode

Then we can create index.html in the public folder and add:

<!DOCTYPE html>  
<html>
<head>  
  <meta charset="utf-8">  
  <meta name="viewport" content="width=device-width">  
  <title>Upload</title>  
  <link href="style.css" rel="stylesheet" type="text/css" />  
</head>
<body>  
  <form action="/upload" method="post" enctype="multipart/form-data">  
    <input type="file" name="upload" />      
    <input type='submit' value='Upload'>  
  </form>  
</body>
</html>
Enter fullscreen mode Exit fullscreen mode

The code for index.html will make the form submit multipart form data.

Also, the value of thename attribute has to match with the name string that’s passed into the upload.single() method.

Once the file is upload, a random ID will be generated for the uploaded file’s name.

req.files will have the file objects and req.body will have the values of the text fields.

Uploading Multiple Files

We can also process the upload of multiple files with the upload.array method as follows:

const express = require('express');  
const bodyParser = require('body-parser');  
const multer = require('multer');  
const upload = multer({ dest: './uploads/' });  
const app = express();
app.use(bodyParser.json());  
app.use(bodyParser.urlencoded({ extended: true }));
app.use(express.static('public'));
app.get('/', (req, res) => {  
  res.sendFile('public/index.html');  
});
app.post('/upload', upload.array('uploads', 5), (req, res) => {  
  res.send('files uploaded')  
});
app.listen(3000, () => console.log('server started'));
Enter fullscreen mode Exit fullscreen mode

Then we have to change index.html to:

<!DOCTYPE html>  
<html>
<head>  
  <meta charset="utf-8">  
  <meta name="viewport" content="width=device-width">  
  <title>Upload</title>  
  <link href="style.css" rel="stylesheet" type="text/css" />  
</head>
<body>  
  <form action="/upload" method="post" enctype="multipart/form-data">  
    <input type="file" name="uploads" multiple />  
    <input type='submit' value='Upload'>  
  </form>  
</body>
</html>
Enter fullscreen mode Exit fullscreen mode

We add the multiple attribute to the form to enable multiple uploads in addition to using the upload.array method.

The 5 in the second argument of the upload.array call is the maximum number of files that we can upload.

Once the file is upload, a random ID will be generated for the uploaded file’s name.

Multiple File Fields

We can enable upload of multiple files as follows:

const express = require('express');  
const bodyParser = require('body-parser');  
const multer = require('multer');  
const upload = multer({ dest: './uploads/' });  
const app = express();
app.use(bodyParser.json());  
app.use(bodyParser.urlencoded({ extended: true }));
app.use(express.static('public'));
app.get('/', (req, res) => {  
  res.sendFile('public/index.html');  
});
const multiUpload = upload.fields([  
  { name: 'photos', maxCount: 3 },  
  { name: 'texts', maxCount: 5 }  
])  
app.post('/upload', multiUpload, (req, res) => {  
  console.log(req.files);  
  res.send('files uploaded');  
});
app.listen(3000, () => console.log('server started'));
Enter fullscreen mode Exit fullscreen mode

Then when we have the following in public/index.html :

<!DOCTYPE html>  
<html><head>  
  <meta charset="utf-8">  
  <meta name="viewport" content="width=device-width">  
  <title>Upload</title>  
  <link href="style.css" rel="stylesheet" type="text/css" />  
</head><body>  
  <form action="/upload" method="post" enctype="multipart/form-data">  
    <label>Photos</label>  
    <br>  
    <input type="file" name="photos" multiple />  
    <br>  
    <label>Texts</label>  
    <br>  
    <input type="file" name="texts" multiple />  
    <br>  
    <input type='submit' value='Upload'>  
  </form>  
</body></html>
Enter fullscreen mode Exit fullscreen mode

We get the files uploaded after we select the files and submit them. The code:

const multiUpload = upload.fields([  
  { name: 'photos', maxCount: 3 },  
  { name: 'texts', maxCount: 5 }  
])
Enter fullscreen mode Exit fullscreen mode

Gets the files from the fields photos and texts and upload to 3 and 5 files respectively.

In the console.log , we see the files of the POST /upload route that we uploaded.

Upload Nothing

To skip the processing of upload files, we can use the upload.none() method as follows:

const express = require('express');  
const bodyParser = require('body-parser');  
const multer = require('multer');  
const upload = multer();  
const app = express();
app.use(bodyParser.json());  
app.use(bodyParser.urlencoded({ extended: true }));
app.use(express.static('public'));
app.get('/', (req, res) => {  
  res.sendFile('public/index.html');  
});
app.post('/submit', upload.none(), (req, res) => {  
  res.send(req.body)  
});
app.listen(3000, () => console.log('server started'));
Enter fullscreen mode Exit fullscreen mode

Then when have the following for public/index.html :

<!DOCTYPE html>  
<html><head>  
  <meta charset="utf-8">  
  <meta name="viewport" content="width=device-width">  
  <title>Upload</title>  
  <link href="style.css" rel="stylesheet" type="text/css" />  
</head><body>  
  <form action="/submit" method="post" enctype="multipart/form-data">  
    <input type="text" name="name" />      
    <input type='submit' value='Submit'>  
  </form>  
</body></html>
Enter fullscreen mode Exit fullscreen mode

We get the submitted POST body in req.body as we can see from the response after typing in something and clicking Submit.

Conclusion

Multer is very useful for processing any kind of multipart forms. It can process uploads of a single file or multiple files. It can also process uploads for multiple fields.

The files uploaded are renamed to an automatically generated by default and are stored in the folder that we specified when we called the multer function to create the middleware.

Also, it can ignore uploaded files and just parse the text request body.

. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .