Introduction
File uploads are a common requirement in Node.js applications. Users may upload profile pictures, documents, PDFs, resumes, or other files through a web application. In this chapter, you will practice the basics of file uploads using Node.js and Express, including multipart form data, Multer, single and multiple file uploads, file validation, file size limits, custom filenames, and practical upload APIs. Node.js File Upload Practice Questions with Solutions help to build concepts.
Question 1: How do you install Multer for file uploads?
Problem
Install the package commonly used with Express for handling multipart/form-data file uploads.
Solution
Create a Node.js project:
mkdir file-upload-practice
cd file-upload-practice
npm init -y
Install Express and Multer:
npm install express multer
Explanation
express is used to create the web server.
multer is middleware designed to handle multipart/form-data, which is the format commonly used when uploading files through HTML forms.
After installation, your project will contain:
file-upload-practice/
│
├── node_modules/
├── package.json
├── package-lock.json
└── index.js
Question 2: How do you create a basic single-file upload?
Problem
Create an Express server that accepts one uploaded file and saves it inside an uploads folder.
Solution
Create index.js:
const express = require("express");
const multer = require("multer");
const app = express();
const upload = multer({
dest: "uploads/"
});
app.post(
"/upload",
upload.single("file"),
(req, res) => {
console.log(req.file);
res.json({
success: true,
message: "File uploaded successfully.",
file: req.file
});
}
);
app.listen(3000, () => {
console.log(
"Server running on http://localhost:3000"
);
});
Start the server:
node index.js
Output
Server running on http://localhost:3000
Step-by-Step Explanation
First import Multer:
const multer = require("multer");
Create an upload handler:
const upload = multer({
dest: "uploads/"
});
This tells Multer to store uploaded files in:
uploads/
The route is:
app.post(
"/upload",
upload.single("file"),
(req, res) => {
single("file") means the server expects one file with the field name:
file
The uploaded file is available through:
req.file
Question 3: How do you control the uploaded file’s filename and destination?
Problem
Configure Multer so that uploaded files are stored inside uploads/ with their original extension and a custom filename.
Solution
const express = require("express");
const multer = require("multer");
const path = require("path");
const app = express();
const storage = multer.diskStorage({
destination: (req, file, callback) => {
callback(null, "uploads/");
},
filename: (req, file, callback) => {
const extension = path.extname(
file.originalname
);
const filename =
`file-${Date.now()}${extension}`;
callback(null, filename);
}
});
const upload = multer({
storage: storage
});
app.post(
"/upload",
upload.single("file"),
(req, res) => {
res.json({
success: true,
message: "File uploaded successfully.",
filename: req.file.filename
});
}
);
app.listen(3000, () => {
console.log(
"Server running on http://localhost:3000"
);
});
Example
Suppose the user uploads:
resume.pdf
The server may save it as:
file-1756000000000.pdf
The exact number will depend on the current time.
Step-by-Step Explanation
We import the path module:
const path = require("path");
Then create disk storage:
const storage = multer.diskStorage({
The destination determines where the file is saved:
destination: (req, file, callback) => {
callback(null, "uploads/");
}
The filename controls the stored filename:
filename: (req, file, callback) => {
We get the original extension:
const extension = path.extname(
file.originalname
);
Then create a new filename:
const filename =
`file-${Date.now()}${extension}`;
Question 4: How do you allow only specific file types?
Problem
Allow only PDF, JPG, JPEG, and PNG files.
Reject all other file types.
Solution
const express = require("express");
const multer = require("multer");
const app = express();
const upload = multer({
dest: "uploads/",
fileFilter: (req, file, callback) => {
const allowedTypes = [
"application/pdf",
"image/jpeg",
"image/png"
];
if (allowedTypes.includes(file.mimetype)) {
callback(null, true);
} else {
callback(
new Error(
"Only PDF, JPG, JPEG and PNG files are allowed."
)
);
}
}
});
app.post(
"/upload",
upload.single("file"),
(req, res) => {
res.json({
success: true,
message: "File uploaded successfully."
});
}
);
app.use((error, req, res, next) => {
res.status(400).json({
success: false,
error: error.message
});
});
app.listen(3000, () => {
console.log(
"Server running on http://localhost:3000"
);
});
Step-by-Step Explanation
Multer provides a fileFilter option:
fileFilter: (req, file, callback) => {
We create an array of allowed MIME types:
const allowedTypes = [
"application/pdf",
"image/jpeg",
"image/png"
];
Then check the uploaded file:
if (allowedTypes.includes(file.mimetype)) {
If allowed:
callback(null, true);
If not:
callback(
new Error("Only PDF, JPG, JPEG and PNG files are allowed.")
);
Question 5: How do you limit the size of an uploaded file?
Problem
Allow file uploads up to 2 MB.
Solution
const express = require("express");
const multer = require("multer");
const app = express();
const upload = multer({
dest: "uploads/",
limits: {
fileSize: 2 * 1024 * 1024
}
});
app.post(
"/upload",
upload.single("file"),
(req, res) => {
res.json({
success: true,
message: "File uploaded successfully."
});
}
);
app.use((error, req, res, next) => {
if (error instanceof multer.MulterError) {
if (error.code === "LIMIT_FILE_SIZE") {
return res.status(400).json({
success: false,
error: "File size must be 2 MB or less."
});
}
}
res.status(400).json({
success: false,
error: error.message
});
});
app.listen(3000, () => {
console.log(
"Server running on http://localhost:3000"
);
});
Step-by-Step Explanation
Multer’s limits option allows us to restrict upload size:
limits: {
fileSize: 2 * 1024 * 1024
}
The calculation is:
1 KB = 1024 bytes
1 MB = 1024 × 1024 bytes
2 MB = 2 × 1024 × 1024 bytes
If the uploaded file exceeds the limit, Multer produces an error with:
LIMIT_FILE_SIZE
We can detect it using:
if (error.code === "LIMIT_FILE_SIZE")
Question 6: How do you upload multiple files?
Problem
Allow a user to upload up to three files using one field named files.
Solution
const express = require("express");
const multer = require("multer");
const app = express();
const upload = multer({
dest: "uploads/"
});
app.post(
"/upload",
upload.array("files", 3),
(req, res) => {
console.log(req.files);
res.json({
success: true,
message: "Files uploaded successfully.",
count: req.files.length
});
}
);
app.listen(3000, () => {
console.log(
"Server running on http://localhost:3000"
);
});
Step-by-Step Explanation
For multiple files, use:
upload.array("files", 3)
The first argument:
files
is the field name.
The second argument:
3
is the maximum number of files accepted.
Uploaded files are available in:
req.files
Question 7: How do you upload different types of files using different fields?
Problem
Create an API that accepts:
- One profile picture.
- Up to two certificates.
Use the field names:
profile
certificates
Solution
const express = require("express");
const multer = require("multer");
const app = express();
const upload = multer({
dest: "uploads/"
});
app.post(
"/profile",
upload.fields([
{
name: "profile",
maxCount: 1
},
{
name: "certificates",
maxCount: 2
}
]),
(req, res) => {
const profile =
req.files.profile || [];
const certificates =
req.files.certificates || [];
res.json({
success: true,
profileCount: profile.length,
certificateCount: certificates.length
});
}
);
app.listen(3000, () => {
console.log(
"Server running on http://localhost:3000"
);
});
HTML Form
<form
action="http://localhost:3000/profile"
method="POST"
enctype="multipart/form-data"
>
<label>Profile Picture:</label>
<input
type="file"
name="profile"
>
<br><br>
<label>Certificates:</label>
<input
type="file"
name="certificates"
multiple
>
<br><br>
<button type="submit">
Upload
</button>
</form>
Step-by-Step Explanation
We use:
upload.fields([
Then define each field:
{
name: "profile",
maxCount: 1
}
and:
{
name: "certificates",
maxCount: 2
}
The uploaded files are available through:
req.files
For example:
req.files.profile
contains the profile picture.
And:
req.files.certificates
contains the certificate files.
Question 8: How do you handle file upload errors?
Problem
Create an upload API that properly handles Multer errors.
Solution
const express = require("express");
const multer = require("multer");
const app = express();
const upload = multer({
dest: "uploads/",
limits: {
fileSize: 2 * 1024 * 1024
}
});
app.post(
"/upload",
upload.single("file"),
(req, res) => {
res.json({
success: true,
message: "File uploaded successfully.",
filename: req.file.filename
});
}
);
app.use((error, req, res, next) => {
if (error instanceof multer.MulterError) {
if (error.code === "LIMIT_FILE_SIZE") {
return res.status(400).json({
success: false,
error: "File is too large."
});
}
return res.status(400).json({
success: false,
error: error.message
});
}
res.status(500).json({
success: false,
error: "Something went wrong."
});
});
app.listen(3000, () => {
console.log(
"Server running on http://localhost:3000"
);
});
Step-by-Step Explanation
Multer errors can be checked using:
error instanceof multer.MulterError
For example, a file-size error can have:
LIMIT_FILE_SIZE
We can provide a friendly response:
return res.status(400).json({
success: false,
error: "File is too large."
});
Question 9: How do you upload a file and return useful file information?
Problem
Create an upload API that returns the original filename, stored filename, MIME type, and file size.
Solution
const express = require("express");
const multer = require("multer");
const app = express();
const upload = multer({
dest: "uploads/"
});
app.post(
"/upload",
upload.single("file"),
(req, res) => {
const file = req.file;
res.json({
success: true,
message: "File uploaded successfully.",
file: {
originalName: file.originalname,
storedName: file.filename,
mimeType: file.mimetype,
size: file.size
}
});
}
);
app.listen(3000, () => {
console.log(
"Server running on http://localhost:3000"
);
});
Example Response
If the user uploads:
resume.pdf
the response will look similar to:
{
"success": true,
"message": "File uploaded successfully.",
"file": {
"originalName": "resume.pdf",
"storedName": "f8a21b3c...",
"mimeType": "application/pdf",
"size": 245678
}
}
The stored filename and exact size will depend on the uploaded file.
Step-by-Step Explanation
Multer provides useful information through:
req.file
Some commonly used properties are:
file.originalname
Original filename.
file.filename
Name used on the server when disk storage is configured.
file.mimetype
Reported MIME type.
file.size
File size in bytes.
Question 10: How do you build a practical secure file upload API?
Problem
Build a beginner-friendly Express file upload API with:
- Custom filename.
- Upload directory.
- File type restrictions.
- 2 MB file-size limit.
- Single-file upload.
- Error handling.
- JSON response.
Allow:
PDF
JPG
JPEG
PNG
Solution
Install the required packages:
npm init -y
npm install express multer
Create index.js:
const express = require("express");
const multer = require("multer");
const path = require("path");
const fs = require("fs");
const app = express();
const uploadDirectory = "uploads";
if (!fs.existsSync(uploadDirectory)) {
fs.mkdirSync(uploadDirectory, {
recursive: true
});
}
const storage = multer.diskStorage({
destination: (req, file, callback) => {
callback(null, uploadDirectory);
},
filename: (req, file, callback) => {
const extension = path.extname(
file.originalname
).toLowerCase();
const filename =
`upload-${Date.now()}-${Math.round(
Math.random() * 1E9
)}${extension}`;
callback(null, filename);
}
});
const allowedTypes = [
"application/pdf",
"image/jpeg",
"image/png"
];
const upload = multer({
storage: storage,
limits: {
fileSize: 2 * 1024 * 1024
},
fileFilter: (req, file, callback) => {
if (
allowedTypes.includes(
file.mimetype
)
) {
callback(null, true);
} else {
callback(
new Error(
"Only PDF, JPG, JPEG and PNG files are allowed."
)
);
}
}
});
app.post(
"/upload",
upload.single("file"),
(req, res) => {
res.status(201).json({
success: true,
message: "File uploaded successfully.",
file: {
originalName: req.file.originalname,
filename: req.file.filename,
mimeType: req.file.mimetype,
size: req.file.size
}
});
}
);
app.use((error, req, res, next) => {
if (error instanceof multer.MulterError) {
if (error.code === "LIMIT_FILE_SIZE") {
return res.status(400).json({
success: false,
error:
"File size must be 2 MB or less."
});
}
return res.status(400).json({
success: false,
error: error.message
});
}
res.status(400).json({
success: false,
error: error.message
});
});
app.listen(3000, () => {
console.log(
"Server running on http://localhost:3000"
);
});
Step-by-Step Explanation
Step 1: Import the modules
const express = require("express");
const multer = require("multer");
const path = require("path");
const fs = require("fs");
We use:
expressfor the server.multerfor multipart file uploads.pathfor working with file extensions.fsfor creating the upload directory.
Step 2: Create the upload directory
if (!fs.existsSync(uploadDirectory)) {
fs.mkdirSync(uploadDirectory, {
recursive: true
});
}
This ensures the directory exists before Multer tries to save the file.
Step 3: Configure storage
const storage = multer.diskStorage({
The destination is:
destination: (req, file, callback) => {
callback(null, uploadDirectory);
}
Step 4: Create a server-side filename
const extension = path.extname(
file.originalname
).toLowerCase();
Then:
const filename =
`upload-${Date.now()}-${Math.round(
Math.random() * 1E9
)}${extension}`;
This avoids simply trusting the user’s original filename.
Step 5: Restrict file types
const allowedTypes = [
"application/pdf",
"image/jpeg",
"image/png"
];
Then check:
allowedTypes.includes(file.mimetype)
Step 6: Limit file size
limits: {
fileSize: 2 * 1024 * 1024
}
This limits the upload to 2 MB.
Step 7: Accept one file
upload.single("file")
The HTML field must use:
<input type="file" name="file">
Step 8: Access the uploaded file
Inside the route:
req.file
contains information about the uploaded file.
Step 9: Return a JSON response
res.status(201).json({
success: true,
message: "File uploaded successfully."
});
Key Takeaways
- File uploads allow users to send files from a client to a Node.js server.
- Express alone does not parse
multipart/form-datafile uploads. - Multer is commonly used with Express to handle
multipart/form-data. upload.single()handles one uploaded file.upload.array()handles multiple files using the same field name.upload.fields()handles multiple file fields with different names.- Uploaded single-file information is available through
req.file. - Uploaded multiple-file information is available through
req.files. multer.diskStorage()allows you to control the upload destination and filename.fileFiltercan be used to reject unwanted file types.limits.fileSizecan restrict the maximum upload size.file.originalnamecontains the original filename supplied by the client.file.filenamecontains the stored filename when disk storage is used.file.mimetypecontains the reported MIME type.file.sizecontains the file size in bytes.enctype="multipart/form-data"is required when uploading files through an HTML form.- The HTML input’s
namemust match the Multer field name. - Server-generated filenames are safer than directly using user-provided filenames.
- File-upload errors should be handled properly.
- Uploaded files should be treated as untrusted data.
- Production applications should use stronger validation and security controls than a basic practice example.
FAQs
1. What is Multer in Node.js?
Multer is middleware for handling multipart/form-data, which is commonly used when uploading files through HTML forms.
Example:
const multer = require("multer");
const upload = multer({
dest: "uploads/"
});
It works commonly with Express applications.
2. Why is enctype=”multipart/form-data” required for file uploads?
A normal HTML form sends simple form data differently.
For file uploads, the form should use:
<form
method="POST"
enctype="multipart/form-data"
>
This allows the browser to send file content along with the other form fields.
3. What is the difference between upload.single() and upload.array()?
upload.single() accepts one file:
upload.single("file")
The uploaded file is available through:
req.file
upload.array() accepts multiple files:
upload.array("files", 3)
The uploaded files are available through:
req.files
4. How can I limit the size of an uploaded file?
Use Multer’s limits option:
const upload = multer({
limits: {
fileSize: 2 * 1024 * 1024
}
});
This example limits the file size to approximately 2 MB.
5. How can I allow only PDF and image files?
Use fileFilter:
const allowedTypes = [
"application/pdf",
"image/jpeg",
"image/png"
];
const upload = multer({
fileFilter: (req, file, callback) => {
if (
allowedTypes.includes(
file.mimetype
)
) {
callback(null, true);
} else {
callback(
new Error("File type not allowed.")
);
}
}
});
Remember that MIME-type checking alone is not sufficient for high-security file validation.
6. Where are uploaded files stored?
It depends on the Multer configuration.
For example:
const upload = multer({
dest: "uploads/"
});
stores uploaded files in the uploads directory.
You can also use multer.diskStorage() when you need control over the filename and destination.
7. Is it safe to directly use the uploaded filename?
It is better not to use the user’s original filename directly as your server-side filename.
Instead, generate a server-side filename:
const filename =
`upload-${Date.now()}${extension}`;
For production applications, also validate the file type and content, restrict permissions, prevent executable uploads where appropriate, and carefully control how uploaded files are served.
Written by Shubhranshu Shekhar, who has trained 20000+ students in coding.
