Using multer diskStorage with Typescript
Asked Answered
Z

4

9

I'm translating a node.js server to typescript.

My funcion with node is:

const storage = multer.diskStorage({
    destination: function (req, file, cb) {
        const dir = './uploads/';
        mkdirp(dir, err => cb(err, dir));
    },
    filename: function (req, file, cb) {
        cb(null, file.originalname)
    }
});

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

router.post('/test', upload.fields({name: 'image'}), async function (req, res, next) {
...
});

But I have a lot of errors. For example I can't set the file argument as Express.File type, 'memoryStorage' does not accept arguments or mkdirp tells me that is not callable.

Zebra answered 28/11, 2019 at 23:21 Comment(0)
A
25

Here's how I did it using the type definitions in the @types/multer.

If you haven't already, first install the type definitions for the multer package:

npm i --save-dev @types/multer

Imports and type aliases

import { Request } from 'express'
import multer, { FileFilterCallback } from 'multer'

type DestinationCallback = (error: Error | null, destination: string) => void
type FileNameCallback = (error: Error | null, filename: string) => void

For storage

export const fileStorage = multer.diskStorage({
    destination: (
        request: Request,
        file: Express.Multer.File,
        callback: DestinationCallback
    ): void => {
        // ...Do your stuff here.
    },

    filename: (
        req: Request, 
        file: Express.Multer.File, 
        callback: FileNameCallback
    ): void => {
        // ...Do your stuff here.
    }
})

For fileFilter

export const fileFilter = (
    request: Request,
    file: Express.Multer.File,
    callback: FileFilterCallback
): void => {
    if (
        file.mimetype === 'image/png' ||
        file.mimetype === 'image/jpg' ||
        file.mimetype === 'image/jpeg'
    ) {
        callback(null, true)
    } else {
        callback(null, false)
    }
}

For cleaner code and separation of concerns, place the above two constants in a separate file like config/multer.ts or util/multer.ts

Usage

Import and use the above constants in app.ts or server.ts:

app.use(multer({ storage: fileStorage, fileFilter: fileFilter })
Alpestrine answered 1/11, 2021 at 14:37 Comment(1)
Express is imported from 'express': import type { Request, Express } from 'express'Niles
D
5

I used the following code and it worked

   const guidGenerator = require('uuid/v1');

   // configurates how the files are gonna be stored
   const storage = multer.diskStorage({
       destination: function (req: Express.Request, file: Express.Multer.File, callback: (error: Error | null, destination: string) => void) {
        callback(null, './upload/');
    },
    filename: function (req: Request, file: Express.Multer.File, callback: (error: Error | null, filename: string) => void) {
        const guid = guidGenerator();
        callback(null, guid + '_' + file.originalname);
    }
});
Dzerzhinsk answered 14/1, 2020 at 3:0 Comment(0)
C
0

In my case, I used this.

const guidGenerator = require('uuid/v1');

const storage = multer.diskStorage({
  destination: (req, file, callback) => {
    callback(null, path.resolve('./upload/'))
  },
  filename: (req, file, callback) => {
    const guid = guidGenerator();
    callback(null, `${guid}-${file.originalname}`);
  }
});
Coronary answered 2/8, 2021 at 5:25 Comment(0)
W
0

I have created a middleware

Middleware:

import multer from 'multer'
import path from 'path'
import { v4 } from 'uuid';

const fileUploadMiddleware = (fieldName: string, dir: string = 'user_image') => {

    return multer({
        storage: multer.diskStorage({
            destination: 'assets/' + dir,
            filename: (req, file, cb) => {
                cb(null, v4() + path.extname(file.originalname));
            }
        }),
        limits: {
            fileSize: 1024 * 1024 * 3
        },
        fileFilter: (req: Express.Request, file: Express.Multer.File, cb: Function) => {
            if (
                file.mimetype === 'image/png' ||
                file.mimetype === 'image/jpg' ||
                file.mimetype === 'image/jpeg'
            ) {
                cb(null, true);
            } else {
                cb(new Error('Only JPEG and PNG images are allowed.'), false);
            }
        }
    }).single(fieldName);
}

export default fileUploadMiddleware;

Route file:

router.patch('/', fileUploadMiddleware('profileImage'), updateUserProfileController);
Wedgwood answered 18/9, 2024 at 17:5 Comment(0)

© 2022 - 2025 — McMap. All rights reserved.