Node.js File Upload Practice Questions with Solutions

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:

  • express for the server.
  • multer for multipart file uploads.
  • path for working with file extensions.
  • fs for 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-data file 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.
  • fileFilter can be used to reject unwanted file types.
  • limits.fileSize can restrict the maximum upload size.
  • file.originalname contains the original filename supplied by the client.
  • file.filename contains the stored filename when disk storage is used.
  • file.mimetype contains the reported MIME type.
  • file.size contains the file size in bytes.
  • enctype="multipart/form-data" is required when uploading files through an HTML form.
  • The HTML input’s name must 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.

Scroll to Top