File upload using multer and transfer to a dedicated folder on Nodejs express application

  1. configure the multer
  2. multer configure as global middleware
  3. helper for re-use to get uploaded image or images path
  4. transfer upload file to a dedicated folder
  5. To upload single file and transfer to dedicated folder
  6. To upload multiple files and transfer to dedicated folder
  7. To remove a file reusable helper
  8. To remove a single file
  9. To remove a multiple files
import multer from 'multer'
import path from 'path'
import fs from 'fs'

const storage = multer.diskStorage({
    destination: (req, file, cb) => {
        const uploadDir = path.join(__dirname, "../../public/files/");
        if (!fs.existsSync(uploadDir)) {
            fs.mkdirSync(uploadDir, { recursive: true });
        }
        cb(null, "public/files");
    },
    filename: (req, file, cb) => {
        const uniqueSuffix = Date.now() + '-' + Math.round(Math.random() * 1E9);
        cb(null, uniqueSuffix + '-' + file.originalname);
    },
});

const upload = multer({
    storage: storage,
    fileFilter: (req, file, cb) => {
        const supportedFile = /jpg|jpeg|png|webp|svg|pdf/;
        const extension = path.extname(file.originalname);

        if (supportedFile.test(extension)) {
            cb(null, true);
        } else {
            cb(new Error('Must be a jpg/png/jpeg/webp/svg file'), false);
        }
    },
});


export default upload;

  1. configure multer
import multer from 'multer';
import path from 'path';
import fs from 'fs';
import { fileURLToPath } from 'url';
import { dirname } from 'path';

// Get __dirname equivalent in ES Modules
const __filename = fileURLToPath(import.meta.url);
const __dirname = dirname(__filename);

const storage = multer.diskStorage({
    destination: (req, file, cb) => {
        const uploadDir = path.join(__dirname, "../../public/files/");
        if (!fs.existsSync(uploadDir)) {
            fs.mkdirSync(uploadDir, { recursive: true });
        }
        cb(null, "public/files");
    },
    filename: (req, file, cb) => {
        const uniqueSuffix = Date.now() + '-' + Math.round(Math.random() * 1E9);
        cb(null, uniqueSuffix + '-' + file.originalname);
    },
});

const upload = multer({
    storage: storage,
    fileFilter: (req, file, cb) => {
        const supportedFile = /jpg|jpeg|png|webp|svg|pdf/;
        const extension = path.extname(file.originalname).toLowerCase();

        if (supportedFile.test(extension)) {
            cb(null, true);
        } else {
            cb(new Error('Must be a jpg/png/jpeg/webp/svg/pdf file'), false);
        }
    },
});

export default upload;
  1. use multer configure as global middleware in your main file (eg: index.js / server.js) so, every request data have to send with form-data.
  // multer configure
    app.use(
        upload.fields([
            { name: "single", maxCount: 1 },
            { name: "multiple", maxCount: 10 },
        ])
    );
  1. I am using a helper for re-using to get uploaded image or images path
// single image file upload -> image path
const returnSingleFilePath = async (files, field = 'single') => {

    let filePath;

    if (files && Object.keys(files).length > 0) {
        if (Array.isArray(files)) {
            filePath = files[0].path;
        } else {
            filePath = files[field]?.[0]?.path;
        }
    }

    return filePath;
}

// mutiple image file upload -> image paths
const returnMultipleFilePath = async (files, field = 'multiple') => {

    let imagesPaths = [];

    if (files && Object.keys(files).length > 0) {
        files[field].map((item) => {
            imagesPaths.push(item.path);
        })
    }

    return imagesPaths;
}

export default {
    returnSingleFilePath,
    returnMultipleFilePath,
}
  1. Also, I am using another helper to transfer upload file to a dedicated folder after uploading. In this help again for re-use I am using two function to transfer single or multiple image. Here, in root there will be exists or create public folder then inside the folder transfer files folder will be automatically create and transfer the file.
import fs from 'fs';
import path from 'path';
import { fileURLToPath } from 'url';
import { dirname } from 'path';

// Get __dirname equivalent in ES Modules
const __filename = fileURLToPath(import.meta.url);
const __dirname = dirname(__filename);

// Function to move file to specific folder
const singleFileTransfer = (filePath, destinationFolder) => {
    const fileName = path.basename(filePath);
    const newFilePath = path.join(__dirname, '../../public', destinationFolder, fileName);
    const fileUrl = `public/${destinationFolder}/${fileName}`; // the new URL of the file

    // Check if the destination folder exists, if not, create it
    if (!fs.existsSync(path.dirname(newFilePath))) {
        fs.mkdirSync(path.dirname(newFilePath), { recursive: true });
    }

    // Move the file to the destination folder
    fs.rename(filePath, newFilePath, (err) => {
        if (err) {
            console.log(`Error moving file: ${err}`);
        } else {
            console.log(`File moved successfully to ${newFilePath}`);
        }
    });

    return fileUrl;
}

// Function to move files to specific folder
const multipleFilesTransfer = async (imagePaths, destinationFolder) => {
    const paths = [];

    imagePaths.map((item) => {
        const newPath = singleFileTransfer(item, destinationFolder);
        paths.push(newPath);
    });

    return paths;
}

export {
    singleFileTransfer,
    multipleFilesTransfer
};
  1. To upload single file and transfer to dedicated folder
const Controller = async (req, res) => {

    const body = req.body && req.body.data ? JSON.parse(req.body.data) : {};

    // getting the images path
    if (req.files && Object.keys(req.files).length > 0) {
        if (req.files.single) {
            const imagePath = await returnFilePath.returnSingleFilePath(req.files, 'single');

            // transfer images to new folder and assign new paths
            if (imagePath) {
                const newImagePath = await singleFileTransfer(imagePath, "folderName")
                body.logo = newImagePath;
            }
        }
    }

    sendResponse(res, {
        statusCode: 200,
        success: true,
        message: 'Api called successfully!',
        data: body,
    });
}
  1. To upload multiple files and transfer to dedicated folder
const Controller = async (req, res) => {

    const body = req.body && req.body.data ? JSON.parse(req.body.data) : {};

    // getting the images path
    if (req.files && Object.keys(req.files).length > 0) {
        // upload images
        const imagePaths = await returnFilePath.returnMultipleFilePath(req.files);

        // transfer images to new folder and assign new paths
        let newImagePaths = [];
        if (imagePaths.length) {
            newImagePaths = await multipleFilesTransfer(imagePaths, "folderName")
            body.photos = newImagePaths;
        }
    }

    sendResponse(res, {
        statusCode: 200,
        success: true,
        message: 'Api called successfully!',
        data,
    });
}
  1. To remove a file I am using a new helper
import fs from 'fs';

const removeFile = async (imgPath) => {
    if (fs.existsSync(imgPath)) {
        fs.unlinkSync(imgPath);
        console.log(`File ${imgPath} deleted successfully`);
    } else {
        console.log(`File ${imgPath} does not exist`);
    }
}

export default removeFile;
  1. To remove a single file, use async in controller
 await removeFile(item);
  1. To remove a multiple files, use async in controller
 imagePaths.map(async (item) => {
     await removeFile(item);
 })

Trang chủ Giới thiệu Sinh nhật bé trai Sinh nhật bé gái Tổ chức sự kiện Biểu diễn giải trí Dịch vụ khác Trang trí tiệc cưới Tổ chức khai trương Tư vấn dịch vụ Thư viện ảnh Tin tức - sự kiện Liên hệ Chú hề sinh nhật Trang trí YEAR END PARTY công ty Trang trí tất niên cuối năm Trang trí tất niên xu hướng mới nhất Trang trí sinh nhật bé trai Hải Đăng Trang trí sinh nhật bé Khánh Vân Trang trí sinh nhật Bích Ngân Trang trí sinh nhật bé Thanh Trang Thuê ông già Noel phát quà Biểu diễn xiếc khỉ Xiếc quay đĩa Dịch vụ tổ chức sự kiện 5 sao Thông tin về chúng tôi Dịch vụ sinh nhật bé trai Dịch vụ sinh nhật bé gái Sự kiện trọn gói Các tiết mục giải trí Dịch vụ bổ trợ Tiệc cưới sang trọng Dịch vụ khai trương Tư vấn tổ chức sự kiện Hình ảnh sự kiện Cập nhật tin tức Liên hệ ngay Thuê chú hề chuyên nghiệp Tiệc tất niên cho công ty Trang trí tiệc cuối năm Tiệc tất niên độc đáo Sinh nhật bé Hải Đăng Sinh nhật đáng yêu bé Khánh Vân Sinh nhật sang trọng Bích Ngân Tiệc sinh nhật bé Thanh Trang Dịch vụ ông già Noel Xiếc thú vui nhộn Biểu diễn xiếc quay đĩa Dịch vụ tổ chức tiệc uy tín Khám phá dịch vụ của chúng tôi Tiệc sinh nhật cho bé trai Trang trí tiệc cho bé gái Gói sự kiện chuyên nghiệp Chương trình giải trí hấp dẫn Dịch vụ hỗ trợ sự kiện Trang trí tiệc cưới đẹp Khởi đầu thành công với khai trương Chuyên gia tư vấn sự kiện Xem ảnh các sự kiện đẹp Tin mới về sự kiện Kết nối với đội ngũ chuyên gia Chú hề vui nhộn cho tiệc sinh nhật Ý tưởng tiệc cuối năm Tất niên độc đáo Trang trí tiệc hiện đại Tổ chức sinh nhật cho Hải Đăng Sinh nhật độc quyền Khánh Vân Phong cách tiệc Bích Ngân Trang trí tiệc bé Thanh Trang Thuê dịch vụ ông già Noel chuyên nghiệp Xem xiếc khỉ đặc sắc Xiếc quay đĩa thú vị
Trang chủ Giới thiệu Sinh nhật bé trai Sinh nhật bé gái Tổ chức sự kiện Biểu diễn giải trí Dịch vụ khác Trang trí tiệc cưới Tổ chức khai trương Tư vấn dịch vụ Thư viện ảnh Tin tức - sự kiện Liên hệ Chú hề sinh nhật Trang trí YEAR END PARTY công ty Trang trí tất niên cuối năm Trang trí tất niên xu hướng mới nhất Trang trí sinh nhật bé trai Hải Đăng Trang trí sinh nhật bé Khánh Vân Trang trí sinh nhật Bích Ngân Trang trí sinh nhật bé Thanh Trang Thuê ông già Noel phát quà Biểu diễn xiếc khỉ Xiếc quay đĩa
Thiết kế website Thiết kế website Thiết kế website Cách kháng tài khoản quảng cáo Mua bán Fanpage Facebook Dịch vụ SEO Tổ chức sinh nhật