Search code examples
node.jsexpressmulter

Modify req.body after file was saved by multer


I can't figure out a simple thing. If I do pass files with the request, I want to save them, and then modify req.body a little bit inside the same multer middleware. My multer middleware:

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

const fileFilter = (req: Request, file: Express.Multer.File, cb: multer.FileFilterCallback) => {
    if (
        file.mimetype === 'audio/wave' ||
        file.mimetype === 'image/png' ||
        file.mimetype === 'image/jpeg'
    )
        return cb(null, true)

    cb(null, false)
}
const upload = multer({
    storage: storage,
    limits: {
        fileSize: 1024 * 1024 * 3, // up to 3 megabytes
    },
    fileFilter: fileFilter,
})

export const saveFiles = upload.fields([
    { name: 'audio', maxCount: 1 },
    { name: 'image', maxCount: 1 },
])

Right now I do it in the router:

if (req.files) {
        if ((req as any).files.audio)
            req.body.data.audio = (req as any).files.audio[0].path.replace('\\', '/')
        if ((req as any).files.image)
            req.body.data.image = (req as any).files.image[0].path.replace('\\', '/')
    }

Which is kinda annoying, I would like to just do it inside the multer somehow before it fires next(). I just can't figure out how.


Solution

  • So, saveFiles is your middleware function. You don't show where you actually use it, but presumably you are registering it in your router as middleware somewhere. Because it's middleware, that means it is a function that expects to be called with the arguments (req, res, next). You can replace that next argument with your own and do your work in their like this:

    // multer's middlware function, we will wrap
    const saveFilesMiddleware = upload.fields([
        { name: 'audio', maxCount: 1 },
        { name: 'image', maxCount: 1 },
    ]);
    
    // wrap the multer middleware with our own
    export const saveFiles = function(req, res, next) {
         saveFilesMiddleware(req, res, err => {
             if (err) {
                 // upon error, just call the real next with the error
                 next(err);
             } else {
                 // when no error, do our housekeeping in req.body
                 if (req.files) {
                    if ((req as any).files.audio)
                         req.body.data.audio = (req as any).files.audio[0].path.replace('\\', '/');
                    if ((req as any).files.image)
                         req.body.data.image = (req as any).files.image[0].path.replace('\\', '/');
                 }
                 next();
             }
         });        
    };