import { NextFunction, Request, Response } from 'express'; import multer, { FileFilterCallback } from 'multer'; import { StaticRoot, sizeLimit } from '../config/Env'; import fs from 'fs/promises'; import path from 'path'; /** * @description The file storage configuration */ export const fileStorage = multer.diskStorage({ destination: (req, file, callback) => { const destination = path.join(StaticRoot, 'documents'); // create folder if not exists fs.mkdir(destination, { recursive: true }) .then(() => { callback(null, destination); }) .catch((e) => { callback({ name: 'Creating Folder', message: e.message }, destination); }); }, filename: (_, file, callback) => { var name = Date.now() + '-' + file.originalname.replace(/\s/g, '-').toLowerCase(); callback(null, name); }, }); /** * @description The file filter configuration */ export const fileFilter = ( request: Request, file: Express.Multer.File, callback: FileFilterCallback ): void => { // document file types if ( file.mimetype === 'application/pdf' || file.mimetype === 'application/msword' || file.mimetype === 'application/vnd.openxmlformats-officedocument.wordprocessingml.document' || file.mimetype === 'application/vnd.ms-excel' || file.mimetype === 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet' || file.mimetype === 'application/vnd.ms-powerpoint' || file.mimetype === 'application/vnd.openxmlformats-officedocument.presentationml.presentation' || file.mimetype === 'application/vnd.oasis.opendocument.text' || file.mimetype === 'application/vnd.oasis.opendocument.presentation' || file.mimetype === 'application/vnd.oasis.opendocument.spreadsheet' ) { if (file.size > sizeLimit) return callback(new Error('File size must be less than 5MB')); callback(null, true); } else { callback(new Error(`Invalid file type ${file.mimetype}`)); } }; /** * @description Delete a file * @param fileName - String * @returns Promise<{ isDeleted: boolean }> */ export const deleteFile = async ( fileName: string ): Promise<{ isDeleted: boolean }> => { const filePath = path.join(StaticRoot, 'documents', fileName); try { await fs.unlink(filePath); return { isDeleted: true }; } catch (error) { return { isDeleted: false }; } }; export const uploadDoc = multer({ storage: fileStorage, fileFilter: fileFilter, }); /** * @description The file storage configuration for thumbnails */ export const fileStorageThumbnails = multer.diskStorage({ destination: (req, file, callback) => { const destination = path.join(StaticRoot, 'thumbnails'); // create folder if not exists fs.mkdir(destination, { recursive: true }) .then(() => { callback(null, destination); }) .catch((e) => { callback({ name: 'Creating Folder', message: e.message }, destination); }); }, filename: (_, file, callback) => { var name = Date.now() + '-' + file.originalname.replace(/\s/g, '-').toLowerCase(); callback(null, name); }, }); /** * @description The file Thumbnail filter configuration */ export const fileFilterThumbnail = ( request: Request, file: Express.Multer.File, callback: FileFilterCallback ): void => { // image file types if ( file.mimetype === 'image/jpeg' || file.mimetype === 'image/png' || file.mimetype === 'image/jpg' ) { if (file.size > sizeLimit) return callback(new Error('File size must be less than 5MB')); callback(null, true); } else { callback(new Error(`Invalid file type ${file.mimetype}`)); } }; /** * @description Delete a file thumbnail * @param fileName - String * @returns Promise<{ isDeleted: boolean }> */ export const deleteFileThumbnail = async ( fileName: string ): Promise<{ isDeleted: boolean }> => { const filePath = path.join(StaticRoot, 'thumbnails', fileName); try { await fs.unlink(filePath); return { isDeleted: true }; } catch (error) { return { isDeleted: false }; } }; export const uploadThumbnail = multer({ storage: fileStorageThumbnails, fileFilter: fileFilterThumbnail, });