Welcome folks today in this blog post we will be be looking on how to upload multiple files inside express.js web server using the multer library with validation and error handling in node.js using javascript. All the full source code of the application is shown below.
Get Started
In order to get started you need to make a node.js project by executing the below commands as shown below
npm init -y
So with the above command we are able to create a package.json file for our node.js project. And now we need to install the dependencies which are required for this project
npm i express
npm i multer
npm i --save-dev nodemon
As you can see we are installing the express web server library and also the multer library which is the most popular library in node.js to upload files to server. After installing the packages now let’s start a very basic web server in express. And also we are installing the nodemon package to restart the server when we make any kind of changes to the app.
index.js
1 2 3 4 5 6 7 |
const express = require('express') const app = express() app.listen(3000,() => { console.log("App is listening on port 3000") }) |
As you can see we are requiring the express library and starting the app at port number 3000. Now to run the node.js app using the below command
nodemon index.js
Uploading Single File Using Multer
Now we need to create a uploads
folder inside the root directory where we will store all the files that the user will be uploading using the html5 form.
Now we will making a simple get route which will show the index.html
file inside index.js
file as shown below
1 2 3 |
app.get('/', (req, res) => { res.sendFile(__dirname + "/index.html") }) |
Now we will be writing this index.html
file which will be shown when anyone opens the homepage of the node.js app
index.html
1 2 3 4 5 6 |
<form action="/uploadfile" enctype="multipart/form-data" method="post"> <div> <input type="file" name="file"> <input type="submit" value="Upload File"> </div> </form> |
As you can see we have the simple html5 form which contains a simple input field where we allow the user to upload the files. And then we have the submit button to upload the file. And when we submit the form a post request is made to the /uploadfile route. And then we are also assigning a enctype multipart/form-data which is required for uploading files.
Initializing the Multer Library
Now we will be initializing the Multer library inside the index.js
file as shown below
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
const express = require('express') const multer = require('multer') const path = require('path') const app = express() var storage = multer.diskStorage({ destination: function (req, file, cb) { cb(null, 'uploads') }, filename: function (req, file, cb) { cb(null, Date.now() + path.extname(file.originalname)) //Appending extension } }) const upload = multer({ storage: storage }) |
As you can see we are importing the multer library. And also we are importing the built in module of path module.
Now after that we are initializing the multer storage engine. And in that initializing multer we are passing the destination where we will be storing the uploaded files. And also we will be providing the filename. Here we are generating the random filename using Date.now() and also we are extracting the extension of the filename.
And then we are passing the storage object to the multer library. In the multer constructor we are passing this storage object.
Making the POST Request to Upload Single File
Now we will be writing the post request to actually upload a single file to the uploads folder that we have created earlier on. For that the code is shown below
1 2 3 |
app.post('/uploadfile', upload.single('file'), function (req, res, next) { console.log(req.file.path) }) |
As you can see we are using the multer middleware in between the request. And it contains a method called as single
which is used to upload a single file at a time. And in that single() method we are passing the name attribute that we have defined inside the index.html file as shown below.
And after that we are simply printing out the path of the uploaded file as shown below
Uploading Multiple Files in Multer
Now guys we will be seeing how to upload multiple files in express.js using multer. Now first of all create a new file called index.html
file and copy paste the below code
multiple.html
1 2 3 4 5 6 |
<form action="/uploadmultiple" enctype="multipart/form-data" method="post"> <div class="form-group"> <input type="file" class="form-control-file" name="files" multiple> <input type="submit" value="Upload Files" class="btn btn-default"> </div> </form> |
As you can see we have now attached a special attribute to the input field which is multiple which allows the user to select multiple files at the time of choosing the files. And also we have changed the action to /uploadmultiple. It is also a post request happening at the server side. And we have provided the name attribute which is equal to files.
And now we need to make a new get route inside the index.js
file as shown below to show this multiple.html
file
1 2 3 |
app.get('/multiple',(req,res) => { res.sendFile(__dirname + "/multiple.html") }) |
Now we will be writing the post request to upload multiple files on the server and store it inside the uploads folder.
1 2 3 4 5 6 7 |
app.post('/uploadmultiple',upload.array('files',50),(req,res) => { if(req.files){ req.files.forEach(file => { console.log(file.path) }); } }) |
As you can see we have this post request to upload multiple files. Again we are using the multer middleware to upload multiple files using multer array() method inside that we are passing the name parameter and the maximum number of files that can be uploaded to server. And after that we are using the foreach loop to loop through each file and printing out the path of the uploaded file.
Storing Files in Memory Storage
As an alternative to diskStorage. We can use the memory storage to store the uploaded files inside the memory. You can initialize it as shown below
1 2 |
const storage = multer.memoryStorage() const upload = multer({ storage: storage }) |
Validating the File Type Extension Using File Filter
Now guys we will be validating the file extension where we will only allow certain file extensions so that we don’t allow unnecessary files that can be allowed by mistake.
1 2 3 4 5 6 7 8 9 10 11 |
const upload = multer({ storage: storage, fileFilter: (req, file, cb) => { if (file.mimetype == "image/png" || file.mimetype == "image/jpg" || file.mimetype == "image/jpeg") { cb(null, true); } else { cb(null, false); return cb(new Error('Only .png, .jpg and .jpeg format allowed!')); } } }) |
As you can see we have defined a file filter inside the multer constructor. Here inside this filter we have defined the if condition where we are comparing the mimetype of the files. Here we are only allowing .png , .jpeg and .jpg extensions to be uploaded. and if any error is there we are showing the error to the user that only these files can be uploaded.
Now we need to show this error message to the user in the browser. It can be done as shown below
1 2 3 4 5 6 7 8 9 10 11 12 |
app.post('/uploadfile', function (req, res) { upload(req, res, function (err) { if (err instanceof multer.MulterError) { console.log(err) } else if (err) { console.log(err) } else { console.log(req.file.path) } }) }) |
As you can see we are uploading the file in this post request. And then we are using the multer.MulterError to check if any file validation error occurred or not. Now if you upload any file other than image you will see the below result on command line
You can even do this for multiple files as well when you upload them is shown below
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 |
const multiple = multer({ storage: storage, fileFilter: (req, file, cb) => { if (file.mimetype == "image/png" || file.mimetype == "image/jpg" || file.mimetype == "image/jpeg") { cb(null, true); } else { cb(null, false); return cb(new Error('Only .png, .jpg and .jpeg format allowed!')); } } }).single('multiple',50) app.post('/uploadmultiple',(req, res) => { multiple(req,res,(err) => { if (req.files) { req.files.forEach(file => { if (err instanceof multer.MulterError) { console.log(err) } else if (err) { console.log(err) } else { console.log(file.path) } }); } }) }) |
Full Source Code
Wrapping it up this is the full source code of the index.js
file. This source code is shown below
index.js
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 |
const express = require('express') const multer = require('multer') const path = require('path') const app = express() var storage = multer.diskStorage({ destination: function (req, file, cb) { cb(null, 'uploads') }, filename: function (req, file, cb) { cb(null, Date.now() + path.extname(file.originalname)) //Appending extension } }) const upload = multer({ storage: storage, fileFilter: (req, file, cb) => { if (file.mimetype == "image/png" || file.mimetype == "image/jpg" || file.mimetype == "image/jpeg") { cb(null, true); } else { cb(null, false); return cb(new Error('Only .png, .jpg and .jpeg format allowed!')); } } }).single('file') const multiple = multer({ storage: storage, fileFilter: (req, file, cb) => { if (file.mimetype == "image/png" || file.mimetype == "image/jpg" || file.mimetype == "image/jpeg") { cb(null, true); } else { cb(null, false); return cb(new Error('Only .png, .jpg and .jpeg format allowed!')); } } }).single('multiple',50) app.get('/', (req, res) => { res.sendFile(__dirname + "/index.html") }) app.get('/multiple', (req, res) => { res.sendFile(__dirname + "/multiple.html") }) app.post('/uploadfile', function (req, res) { upload(req, res, function (err) { if (err instanceof multer.MulterError) { console.log(err) } else if (err) { console.log(err) } else { console.log(req.file.path) } }) }) app.post('/uploadmultiple',(req, res) => { multiple(req,res,(err) => { if (req.files) { req.files.forEach(file => { if (err instanceof multer.MulterError) { console.log(err) } else if (err) { console.log(err) } else { console.log(file.path) } }); } }) }) app.listen(3000, () => { console.log("App is listening on port 3000") }) |