Paramclasses Academy - Blog

Tutorials Details

←
Post 30 of 40
→

File Uploads in Node.js with Express and Multer: Image, PDF and Document Upload Tutorial

File Uploads in Node.js with Express and Multer: Image, PDF and Document Upload Tutorial

October 30, 2026

✦ File Uploads in Node.js with Express and Multer: Image, PDF and Document Upload Tutorial

File uploading is a common feature in modern web applications. Websites often allow users to upload profile pictures, documents, invoices, certificates, product images, and PDF files.

If you are developing a school management system, hospital management system, e-commerce website, or admin panel, you may need a file upload feature.

Node.js makes file uploading possible with packages such as Multer. Multer is middleware for Express.js that handles multipart/form-data, which is the format commonly used when uploading files through HTML forms and Postman.

In this practical tutorial, you will learn how to upload images, PDF files, and documents using Node.js, Express.js, and Multer.

✦ What Is Multer in Node.js?

Multer is an Express.js middleware used to handle file uploads.

When a user selects a file and submits a form, Multer processes the uploaded file and makes its information available to your application.

Multer provides useful features such as:

  • Single file uploads.

  • Multiple file uploads.

  • File storage configuration.

  • File size restrictions.

  • File type filtering.

  • Access to uploaded file information.

For example, you can use Multer to upload:

  • JPG and PNG images.

  • PDF documents.

  • Word documents.

  • Product images.

  • Student certificates.

  • Employee documents.

✦ How File Uploading Works

The file upload process generally follows these steps:

  1. The user selects a file.

  2. The browser sends the file using multipart/form-data.

  3. Express receives the upload request.

  4. Multer processes the file.

  5. Multer validates the file according to your configuration.

  6. The file is saved in the specified folder.

  7. The server sends a response to the client.

✦ Step 1: Create a Node.js Project

Create a project folder:

mkdir nodejs-file-upload
cd nodejs-file-upload
npm init -y

Install Express and Multer:

npm install express multer

Our project structure will look like this:

nodejs-file-upload/
│
├── uploads/
├── server.js
├── package.json
└── .gitignore

The uploads folder will store the uploaded files.

✦ Step 2: Import Required Packages

Create server.js:

const express = require("express");
const multer = require("multer");
const path = require("path");
const crypto = require("crypto");
const fs = require("fs");

const app = express();

app.use(express.json());

Here:

  • express creates our web server.

  • multer handles file uploads.

  • path helps manage file paths.

  • crypto generates unique file names.

  • fs helps create the upload directory.

✦ Step 3: Create the Upload Folder

We need a folder where uploaded files will be stored.

Add this code to server.js:

const uploadDir = path.join(__dirname, "uploads");

if (!fs.existsSync(uploadDir)) {
    fs.mkdirSync(uploadDir, {
        recursive: true
    });
}

This checks whether the uploads folder exists. If it does not exist, Node.js creates it.

✦ Step 4: Configure Multer Storage

Multer supports two common storage methods:

1. DiskStorage: Saves uploaded files on the server's disk.

2. MemoryStorage: Keeps uploaded files in memory as buffers.

For this beginner tutorial, we will use DiskStorage.

Add the following code:

const storage = multer.diskStorage({

    destination: function (req, file, cb) {

        cb(null, uploadDir);

    },

    filename: function (req, file, cb) {

        const extensionMap = {
            "image/jpeg": ".jpg",
            "image/png": ".png",
            "application/pdf": ".pdf",
            "application/msword": ".doc",
            "application/vnd.openxmlformats-officedocument.wordprocessingml.document": ".docx"
        };

        const extension = extensionMap[file.mimetype];

        const uniqueName =
            crypto.randomBytes(16).toString("hex") + extension;

        cb(null, uniqueName);

    }

});

Understanding the code:

  • destination specifies where the uploaded file will be saved.

  • filename generates a unique name for each file.

  • crypto.randomBytes() helps avoid filename collisions.

  • The extension is selected from an allowlist rather than trusting the original filename.

Using unique names also helps prevent users from overwriting files with identical original names.

✦ Step 5: Add File Type Validation

We do not want users to upload every type of file.

For example, our application will allow only:

  • JPG images.

  • PNG images.

  • PDF documents.

  • DOC files.

  • DOCX files.

Add this configuration:

const fileFilter = (req, file, cb) => {

    const allowedTypes = [
        "image/jpeg",
        "image/png",
        "application/pdf",
        "application/msword",
        "application/vnd.openxmlformats-officedocument.wordprocessingml.document"
    ];

    if (allowedTypes.includes(file.mimetype)) {

        cb(null, true);

    } else {

        cb(new Error("Only JPG, PNG, PDF, DOC and DOCX files are allowed"));

    }
};

The fileFilter checks the MIME type reported for the uploaded file.

Security note: MIME type is supplied by the client and can be spoofed. This check is useful for basic filtering, but production applications should also inspect file contents using a trusted file-type detection method and consider malware scanning.

✦ Step 6: Configure Multer File Size Limit

Large files can consume server storage and resources.

We can restrict uploads to 5 MB:

const upload = multer({

    storage: storage,

    fileFilter: fileFilter,

    limits: {
        fileSize: 5 * 1024 * 1024
    }

});

Here, 5 * 1024 * 1024 means 5 MB.

You can change the limit according to your application's requirements.

✦ Step 7: Create a Single File Upload API

Now create an API endpoint that accepts one file.

Add this code to server.js:

app.post("/api/upload", upload.single("file"), (req, res) => {

    if (!req.file) {

        return res.status(400).json({
            message: "Please select a file"
        });

    }

    res.status(201).json({

        message: "File uploaded successfully",

        file: {
            filename: req.file.filename,
            originalname: req.file.originalname,
            mimetype: req.file.mimetype,
            size: req.file.size
        }

    });

});

The important method is:

upload.single("file")

It tells Multer to accept one uploaded file from a form field named file.

The uploaded file information is available through:

req.file

✦ Step 8: Add Error Handling

Multer may reject a file because of its size or file type. We should return a clear error response.

Add this error-handling middleware after your upload route:

app.use((err, req, res, next) => {

    if (err instanceof multer.MulterError) {

        if (err.code === "LIMIT_FILE_SIZE") {

            return res.status(400).json({
                message: "File size must not exceed 5 MB"
            });

        }

        return res.status(400).json({
            message: err.message
        });

    }

    if (err) {

        return res.status(400).json({
            message: err.message
        });

    }

    next();

});

This handles Multer-specific errors and file validation errors.

✦ Step 9: Start the Node.js Server

Add this code at the end of server.js:

const PORT = 3000;

app.listen(PORT, () => {

    console.log(`Server running at http://localhost:${PORT}`);

});

Your complete beginner project is now ready.

Run the application:

node server.js

You should see:

Server running at http://localhost:3000

✦ Step 10: Test File Upload Using Postman

Open Postman and create a new request.

Request Method: POST

URL:

http://localhost:3000/api/upload

Follow these steps:

  1. Select the Body tab.

  2. Choose form-data.

  3. Enter the key file.

  4. Change its type from Text to File.

  5. Select an image or document from your computer.

  6. Click Send.

A successful response will look like this:

{
    "message": "File uploaded successfully",
    "file": {
        "filename": "generated-unique-filename.jpg",
        "originalname": "profile.jpg",
        "mimetype": "image/jpeg",
        "size": 245678
    }
}

The generated filename will be different for each upload.

Open your project folder and check the uploads directory. You should find the uploaded file there.

✦ Step 11: Create an HTML File Upload Form

You can also upload files through a simple HTML form.

Create index.html:

<!DOCTYPE html>
<html>
<head>
    <title>Node.js File Upload</title>
</head>
<body>

    <h2>Upload Image or Document</h2>

    <form
        action="http://localhost:3000/api/upload"
        method="POST"
        enctype="multipart/form-data"
    >

        <input
            type="file"
            name="file"
            accept=".jpg,.jpeg,.png,.pdf,.doc,.docx"
            required
        >

        <button type="submit">
            Upload File
        </button>

    </form>

</body>
</html>

The most important attribute is:

enctype="multipart/form-data"

Without this encoding, the browser will not submit the file in the expected upload format.

The accept attribute helps users choose the intended file types, but it is not a security control. Server-side validation is still required.

✦ Single File Upload vs Multiple File Upload

Multer supports both single and multiple file uploads.

Single file upload:

upload.single("file")

Access the uploaded file using:

req.file

Multiple file upload:

upload.array("files", 5)

Access uploaded files using:

req.files

For example, to accept up to five files:

app.post(
    "/api/upload-multiple",
    upload.array("files", 5),
    (req, res) => {

        res.json({
            message: "Files uploaded successfully",
            totalFiles: req.files.length
        });

    }
);

The client must send files using the same field name, files.

✦ Important File Upload Security Best Practices

When building a real-world file upload system, follow these practices:

  1. Allow only the file types your application actually needs.

  2. Set file size and file count limits.

  3. Generate unique server-side filenames.

  4. Do not trust the original filename or client-provided MIME type.

  5. Validate file contents, not just file extensions.

  6. Store private documents outside publicly accessible folders.

  7. Require authentication and authorization for private uploads.

  8. Use malware scanning where appropriate.

  9. Restrict access to uploaded files.

  10. Keep upload directories protected from executable file handling.

For sensitive documents, do not expose the uploads directory using public static file serving. Build an authenticated download endpoint instead.

✦ Frequently Asked Questions

Q1. What is Multer in Node.js?

Multer is Express.js middleware that handles file uploads using multipart/form-data.

Q2. Can Multer upload images and PDF files?

Yes. You can configure Multer to accept image formats, PDF files, Word documents, and other required file types.

Q3. What is the difference between req.file and req.files?

req.file contains information about a single uploaded file. req.files contains information about multiple uploaded files.

Q4. How can we limit file size in Multer?

Use the limits option and set fileSize in bytes.

Q5. Can we store uploaded files in MySQL?

A common approach is to store the actual files on disk or in object storage and save their filenames, paths, and metadata in MySQL. This makes file management easier for many applications.

✦ Conclusion

File uploading is an important feature of modern backend development. With Node.js, Express.js, and Multer, you can build file upload functionality for images, PDF documents, certificates, and other files.

In this tutorial, we learned how to configure Multer storage, validate file types, set file size limits, create upload APIs, and test file uploads using Postman and HTML forms.

Practice this project and try adding file uploads to a student registration form, employee management system, or e-commerce application.

Learn practical Node.js, Express.js, MySQL, REST API Development, and Backend Programming with Param Classes.

←
Post 30 of 40
→