In this tutorial, we’re gonna build Rest Api to upload multiple files in Node.js using Multer.
Related Posts:
– Node.js Express File Upload/Download Rest API example
– Node.js Express File Upload to Google Cloud Storage example
– 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
– Node.js: Upload/Import Excel file data into MySQL Database
Upload multiple files in Node.js
Before going to the practice part, I’ll show you a couple of things to notice.
In HTML, we need a form with:
– action="/multiple-upload"
– enctype="multipart/form-data"
– multiple
input
<form action="/multiple-upload" method="POST" enctype="multipart/form-data">
...
<input type="file" multiple>
...
</form>
With the action "/multiple-upload"
and POST
method, we use Express Router
for the endpoint and controller to handle upload files:
const express = require("express");
const router = express.Router();
const uploadController = require("../controllers/upload");
let routes = app => {
router.post("/multiple-upload", uploadController.multipleUpload);
return app.use("/", router);
};
The controller calls a middleware that uses Multer disk storage engine:
var storage = multer.diskStorage({
destination: function (req, file, callback) {
callback(null, '/path/to/uploads')
},
filename: function (req, file, callback) {
callback(null, file.fieldname + '-' + Date.now())
}
});
var upload = multer({ storage: storage });
You can see that we have two options here:
– destination
determines folder to store the uploaded files.
– filename
determines the name of the file inside the destination
folder.
Demo for upload multiple files
Open the app:
Choose the images to upload:
Click on Submit button, if the process is successful, you can see the files in upload folder:
If the number of files we choose is larger than 10 (I will show you how to set the limit later):
Practice
Now this is the time for building our app.
Project Structure
Look at the project structure:
You can see that we have these main parts:
– upload
: the folder for storing uploaded files.
– views/index.html
: contains HTML form for user to upload files.
– routes/web.js
: defines routes for endpoints that is called from views, use controllers to handle requests.
– controllers
: home.js
to show views/index.html
, upload.js
to handle upload multiple files with middleware
.
– middleware/upload.js
: initializes Multer disk storage engine.
– server.js
: initializes routes, runs Express app.
Setup Node.js modules
We need to install 2 packages: express
and multer
.
So run the command:
npm install express multer
Create view
Under views folder, create index.html
:
<!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 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 multiple files - bezkoder.com</h4>
<form action="/multiple-upload" method="POST" enctype="multipart/form-data">
<div class="form-group">
<label for="example-input-file"> </label>
<input type="file" name="multi-files" multiple id="input-multi-files" class="form-control-file border"/>
</div>
<button type="submit" class="btn btn-primary">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-multi-files").on("change", function() {
imagesPreview(this, "div.preview-images");
});
});
</script>
</body>
</html>
The script above helps us show preview of the chosen files. To make things simple, I don’t explain it deeply in the tutorial.
Create middleware for upload multiple files
Inside middleware folder, create upload.js
:
const util = require("util");
const path = require("path");
const multer = require("multer");
var storage = multer.diskStorage({
destination: (req, file, callback) => {
callback(null, path.join(`${__dirname}/../../upload`));
},
filename: (req, file, callback) => {
const match = ["image/png", "image/jpeg"];
if (match.indexOf(file.mimetype) === -1) {
var message = `${file.originalname} is invalid. Only accept png/jpeg.`;
return callback(message, null);
}
var filename = `${Date.now()}-bezkoder-${file.originalname}`;
callback(null, filename);
}
});
var uploadFiles = multer({ storage: storage }).array("multi-files", 10);
var uploadFilesMiddleware = util.promisify(uploadFiles);
module.exports = uploadFilesMiddleware;
– We define a storage configuration object, then use multer
module to initialize middleware and util.promisify()
to make the exported middleware object can be used with async-await
.
– To limit the number of files to upload each time, we use array()
function with the first parameter is the name of input
tag (in html view: <input type="file" name="multi-files">
), the second parameter is the max number of files.
– We also check if the file is an image or not using file.mimetype
. Then we add the [timestamp]-bezkoder-
prefix to the file’s original name to make sure that the duplicates never occur.
If you want to do more, for example, resize the images, please visit this post:
Upload & resize multiple images in Node.js using Express, Multer, Sharp
Create controllers
we create 2 files in controllers folder:
home.js
const path = require("path");
const home = (req, res) => {
return res.sendFile(path.join(`${__dirname}/../views/index.html`));
};
module.exports = {
getHome: home
};
upload.js
const upload = require("../middleware/upload");
const multipleUpload = async (req, res) => {
try {
await upload(req, res);
console.log(req.files);
if (req.files.length <= 0) {
return res.send(`You must select at least 1 file.`);
}
return res.send(`Files has been uploaded.`);
} catch (error) {
console.log(error);
if (error.code === "LIMIT_UNEXPECTED_FILE") {
return res.send("Too many files to upload.");
}
return res.send(`Error when trying upload many files: ${error}`);
}
};
module.exports = {
multipleUpload: multipleUpload
};
Define routes
Under routes folder, define routes in web.js
:
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.multipleUpload);
return app.use("/", router);
};
module.exports = routes;
There are 2 routes:
- GET: Home page for the upload form.
- POST "/multiple-upload"
to call the upload controller.
Create Express app server
The last thing to do is creating 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
On the project root folder, run this command:
node src/server.js
The console shows:
Running at localhost:3000
Now you can open browser with url http://localhost:3000/
to check the result.
Conclusion
Today we’ve learned way to build Node.js Rest Api to upload multiple files using Multer, Express, we also know how to limit the number of files and only accept image format such as jpeg/png.
If you want to build server that exports upload/download APIs, please visit:
Node.js Express File Upload/Download Rest API example
Working with GCS:
Node.js Express File Upload to Google Cloud Storage example
You also know way to both upload & resize multiple images in the tutorial:
Upload & resize multiple images in Node.js using Express, Multer, Sharp
Or Upload/store images in MySQL using Node.js, Express & Multer
Happy learning! See you again.
Further Reading
Source Code
You can find the complete source code for this example on Github.
Hi, very good tutorial. What change I need to do to the code if I want upload PDF as well??
I found it out how to do it.
Obviously like your tutorial! I will certainly come back again for more Node.js articles.
thank you in advance!
The demo couldn’t upload mult files. The Demo can upload 1 file only.
Please give me a hand.
sorry. It works well. I should click multi files at once. thank you!
Wonderful, muchas gracias por tan valiosa informacion
Thanks for this Node.js upload file tutorial! This is very helpful for me.
Thank you for this Node.js tutorial! Keep it up.
Greetings from Florida! Thank you for this Nodejs tutorial. Please write a tutorial for upload & resize image files. Thanks!
Hi, this is the tutorial you need:
Upload & resize multiple images in Node.js using Express, Multer, Sharp