We use Node.js to build web application backend and one of the use cases that comes often is a file upload feature. In this tutorial, we are going to learn and build an application that can let user upload multiple files using Node.js.
Our application :
I am going to develop same application as I have done in last tutorial with some additional code changes which makes it multiple file upload.
We are going to use basic FORM submit along with Ajax submit jQuery plugin to make it asynchronous. Here is our package.json file.
"name": "file_upload",
"version": "0.0.1",
"dependencies": {
"body-parser": "^1.14.2",
"express": "4.13.3",
"multer": "1.1.0"
},
"devDependencies": {
"should": "~7.1.0",
"mocha": "~2.3.3",
"supertest": "~1.1.0"
}
}
Run following command to install the dependencies.
Here is our Server file with multiple file upload support.
var bodyParser = require("body-parser");
var multer = require('multer');
var app = express();
app.use(bodyParser.json());
var storage = multer.diskStorage({
destination: function (req, file, callback) {
callback(null, './uploads');
},
filename: function (req, file, callback) {
callback(null, file.fieldname + '-' + Date.now());
}
});
var upload = multer({ storage : storage }).array('userPhoto',2);
app.get('/',function(req,res){
res.sendFile(__dirname + "/index.html");
});
app.post('/api/photo',function(req,res){
upload(req,res,function(err) {
//console.log(req.body);
//console.log(req.files);
if(err) {
return res.end("Error uploading file.");
}
res.end("File is uploaded");
});
});
app.listen(3000,function(){
console.log("Working on port 3000");
});
The only line you need to put your focus on is this
Here rather than .single() we are using .array(selector,fileLimit) of Multer. Multer will accept array of files limiting to max 2 file at each time. You can of course increase the number as you may need. Rest of the code is same as previous tutorial.
Here is our HTML file.
<head>
<title>File upload Node.title>
head>
<body>
<form id="uploadForm"
enctype="multipart/form-data"
action="/api/photo"
method="post">
<input type="file" name="userPhoto" multiple />
<input type="submit" value="Upload Image" name="submit">
<input type='text' id='random' name='random'><br>
<span id = "status">span>
form>
body>
html>
Here is our JavaScript code which we place in same HTML file. You can place it in different file. Put this code below closing tag of BODY.
<script src="http://cdnjs.cloudflare.com/ajax/libs/jquery.form/3.51/jquery.form.min.js">script>
<script>
$(document).ready(function() {
$('#uploadForm').submit(function() {
$("#status").empty().text("File is uploading...");
$(this).ajaxSubmit({
error: function(xhr) {
status('Error: ' + xhr.status);
},
success: function(response) {
console.log(response)
$("#status").empty().text(response);
}
});
return false;
});
});
script>
On Form submit, we will stop the page refresh by returning FALSE and call the API using ajaxSubmit(). You can Add this code in separate file and add it below the jquery.form or copy and paste just below this line.
Running the application
To run the application, switch to project directory and type following command.
Visit localhost:3000 to view the app. Choose multiple files from the selection window and see the console.
Further enhancement
If you want to have different control for file rather than single HTML control then you need to define multiple files control in HTML with same name in order to recognize the Multer that it is array of files. Here is how you can do this. Currently we are using this.
You can write same like this.
There is no change in back-end code required for above change.
Further Study
File uploads using Node.js
Ajax file upload in Node.js
Node.js MySQL Tutorial
HTML5 Push Notification System Using Nodejs MySQL Socket.io
Conclusion
Multer is one of the easy node modules you can use with Express for file upload. It allows you to add various validation and support single as well as multiple file uploads.
how to check the user validation before the file get uploaded.
You need to write an middle ware which does the validation if its common for all routes. Other wise use login mechanism to handle session and use session to check before uploading the file.
Just wondering but What’s the purpose of this part?
Which part ?
oh sorry i must’ve forgot to past it.
part. I’m guessing you can submit extra text data with each file(like file descriptions/captions) that you can store in the database?
Yes you can. req.files object contains all meta information of file.
how can i get the filename as a callback sice its generated randomly i need to pass it to the user
how can i know the filename since its random i need to send it to the user to handle it.
Remove the rename callback from code.
Thank you for this simple, but useful example. I couldn’t figure out how to handle multer’s limits error until I read this. Great stuff.
i tried many times to use filters but it is not working how can i use filters in multer please help me
Very very good article!
Works flawlessly! 😀 Thanks!
I have a problem. Instead of returning to Ajax I get white page displayed with sentence “File is uploaded”. Seems like code is not returning from server to Ajax.
Very nice, thanks
Great help! Do you perhaps no how to write the images names to get the names of the images as they are saved to uploads. I am wanting to use the names and save them as urls to a mongodb, so that I can retrieve the images to be added to an img tag with angular.
Sure. If you visit this link, you see I am using the URL to store and retrieve the image.
how to restrict file formats while uploading
You need to add a callback function in Multer instance.
if (["png","gif"].indexOf(file.originalname.split('.')[file.originalname.split('.').length-1]) === -1) {
return callback(new Error('Wrong extension type'));
}
callback(null, true);
}
why it says file uploading error?
file uploaded but no extension..
That is because we are stripping it on second callback in multer constructor.
how can i get extension with filename e.g abc.jpg ??
Thanx for this tutorial.. i got exact filename with extension. 🙂
sir can you help me with uploading files in mongodb using skipper-gridfs adapter
i am getting error ” Cannot find module ‘/../build/Release/bson’ “.
i am developing a project using Node.js and Angular2 , i have huge amount of objects in an array and send that using http.post() method to node server but server works on array and take more than 2 minutes and before response from server my application throws Uncaught Error : ERR_EMPTY_RESPONSE url : null , can you please suggest me solution to that.
how to upload mutiple files with one browe button?
Here it is.
very nice tutorial thanks sir
I have not tried it but I hope it works.
Really helpful… Can we do this for rest api. When data(image,video) recieve in base64?
multer.diskStorage is not a function
How would I go about downloading an image from firebase storage to an html page with a element?