Click Below to subscribe

How to Upload Single Or Multiple Files in Node.js Express

In this article, we gonna learn how to upload single/multiple files in node.js (express).

1. Let's create a new express project using express generator.

npm i -g express-generator
express node-file-upload --view=hbs
cd node-file-upload

2. Install multer and uniqid npm packages.

npm i multer, uniqid

Multer adds a body object and a file or files object to the request object. The body object contains the values of the text fields of the form, the file or files object contains the files uploaded via the form.

Ref:- https://www.npmjs.com/package/multer

file object

{
    fieldname: 'file',
    originalname: 'pic1.png',
    encoding: '7bit',
    mimetype: 'image/png',
    destination: 'storage/',
    filename: '165324457049116ry1ihkl3hn4qrg.png',
    path: 'storage\\165324457049116ry1ihkl3hn4qrg.png',
    size: 339337
}

3. create a folder helpers and inside this folder create a file uploader.js

const multer = require('multer');
const uniqid = require('uniqid'); 
const path = require('path');

const storage = multer.diskStorage({
    destination: (req, file, cb) => {
        cb(null, 'storage/uploads/')
    },
    filename: (req, file, cb) => {
        cb(null, Date.now() + uniqid() + path.extname(file.originalname))
    }
});

const upload = multer({ storage: storage }); 

module.exports = upload;

4. Create a storage folder and inside this create uploads folder.

5. Create a folder controllers and inside this folder create upload.controller.js

controllers/upload.controller.js

const upload = require("../helpers/uploader");
const util = require("util");

exports.index = (req, res) => {
    return res.render('index', { message: req.flash() });
}

exports.uploadSingle = (req, res) => {
    if (req.file) {
        console.log(req.file)

        req.flash('success', 'File Uploaded.');
    }
    return res.redirect('/');
}

exports.uploadMultiple = (req, res) => {
    if (req.files.length) {
        console.log(req.files)

        req.flash('success', 'Files Uploaded.');
    }
    return res.redirect('/');
}

exports.uploadSingleV2 = async (req, res) => {
    const uploadFile = util.promisify(upload.single('file'));
    try {
        await uploadFile(req, res);
        console.log(req.file)
        
        req.flash('success', 'File Uploaded.');
    } catch (error) {
        console.log(error)
    }
    return res.redirect('/');
}

Note:- For flash messages, I am using connect-flash package.

6. Update routes.

routes/index.js

const express = require('express');
const router = express.Router();
const upload = require('../helpers/uploader');
const uploadController = require('../controllers/upload.controller');

router.get('/',                                           uploadController.index);
router.post('/upload-single',   upload.single('file'),    uploadController.uploadSingle);
router.post('/upload-multiple', upload.array('files', 5), uploadController.uploadMultiple);

/* ------------------------ upload and error handling ----------------------- */
router.post('/upload-single-v2',                          uploadController.uploadSingleV2);

module.exports = router;

7. Open views/index.hbs and add the following code.

<main>
    <div class="row mb-2">
        <div class="col-sm-8 offset-2"> 
            {{#each message}}
                <p class="alert alert-{{@key}}">{{ this.[0] }}</p>
            {{/each}}
            <div class="row">
                <div class="col-md-4">
                    <h6>Upload Single</h6>
                </div>
                <div class="col-md-6">
                    <form method="POST" action="/upload-single" enctype="multipart/form-data"> 
                        <div class="input-group">
                            <div class="custom-file">
                                <input type="file" name="file" class="custom-file-input" id="inputFileSingle" required accept="image/*">
                                <label class="custom-file-label" for="inputFileSingle">Choose file</label>
                            </div>
                            <div class="input-group-append">
                                <button type="submit" class="btn btn-primary float-right mr-2">Upload <i class="fa fa-upload"></i></button>
                            </div>
                        </div>
                    </form>
                </div>
            </div>
            <div class="row">
                <div class="col-md-4">
                    <h6>Upload Multiple</h6>
                </div>
                <div class="col-md-6">
                    <form method="POST" action="/upload-multiple" enctype="multipart/form-data"> 
                        <div class="input-group">
                            <div class="custom-file">
                                <input type="file" name="files" class="custom-file-input" id="inputFileMultiple" required accept="image/*" multiple>
                                <label class="custom-file-label" for="inputFileMultiple">Choose file</label>
                            </div>
                            <div class="input-group-append">
                                <button type="submit" class="btn btn-primary float-right mr-2">Upload <i class="fa fa-upload"></i></button>
                            </div>
                        </div>
                    </form>
                </div>
            </div> 
            <div class="row">
                <div class="col-md-4">
                    <h6>Upload Single (Error Handling)</h6>
                </div>
                <div class="col-md-6">
                    <form method="POST" action="/upload-single-v2" enctype="multipart/form-data"> 
                        <div class="input-group">
                            <div class="custom-file">
                                <input type="file" name="file" class="custom-file-input" id="inputFileSingle" required accept="image/*">
                                <label class="custom-file-label" for="inputFileSingle">Choose file</label>
                            </div>
                            <div class="input-group-append">
                                <button type="submit" class="btn btn-primary float-right mr-2">Upload <i class="fa fa-upload"></i></button>
                            </div>
                        </div>
                    </form>
                </div>
            </div>
        </div>
    </div>
</main>

8. Finally start the project.

npm start

Open http://localhost:3000 and try to upload files.

Access file from storage's uploads folder

If you want to access files then you need to use static middleware.

Ref- https://expressjs.com/en/starter/static-files.html

app.use(express.static(path.join(__dirname, 'storage')));

Example:-

<img src="/uploads/pic.png">

Checkout my full node-file-upload example.

https://github.com/ultimateakash/node-file-upload

If you facing any issues. don't hesitate to comment below. I will be happy to help you.

Thanks.

Leave Your Comment