hello I am trying to create a custom middle-ware for file upload with multer with customization (allowed file type, destination folder ...). the upload is working but the req.file is always undefined, below you can find my code edit : I have changed the code images to code snippets to make it easier to copy thank you
// route
router.patch('/profile-picture',
[
AsyncErrorWrapper(passport.verifyJwt()),
AsyncErrorWrapper(singleFileUpload('/images/', ['image/png', 'image/jpeg'])),
], AsyncErrorWrapper(userController.updateProfilePicture))
// singleFileUpload
const {uploadConfiguration, multerDelay} = require("../services/multer.service")
/**
*
* @param {*} dest destination folder inside the /tmp
* @param {*} whitelist list of extensions which are allowed to be uploaded
* @returns
*/
module.exports = (dest, whitelist, name = 'file') => {
return async (req, res, next) => {
// get the upload config obj
const upload = uploadConfiguration(dest, whitelist)
// call the upload.single
upload.single(name)(req, res, next)
// make sur we wait for the upload to finish to solve the req.file is undefined
await multerDelay()
next()
}
}
// service
const uploadConfiguration = (dest, whitelist) => {
// storage
const storage = multer.diskStorage({
destination: (req, file, cb) => {
// set the directory
const dir = `${tmpStorage}${dest}`
mkdirp.sync(dir)
cb(null, dir)
},
filename: (req, file, cb) => {
cb(null, Date.now() path.extname(file.originalname));
},
})
// upload filter
const uploadFilter = (req, file, cb) => {
if (!whitelist.includes(file.mimetype)) {
return cb(new AppError('file type is not allowed', 400), false)
}
// make this to solve problem with req.file is undefined in the following middleware
req.file = file
cb(null, true)
}
return multer({
storage: storage,
fileFilter: uploadFilter
})
}
/**
*
* @returns promise that resolve after the queue is clear
*/
const multerDelay = () => {
console.log('multerDelay');
return new Promise((resolve) => setTimeout(() => resolve(), 0))
}
// controller
const updateProfilePicture = async (req, res, next) => {
console.log(req.file) // undefined
return res.status(200).json({msg: 'hi'})
}
CodePudding user response:
The issue is, you can't run a middleware like that
When you do
upload.single(name)(req, res, next)
You are passing next
to the function to run it internally
Running next
more than once will always cause errors
You should split it into two functions
// singleFileUpload
module.exports = (dest, whitelist, name = 'file') => {
return async (req, res, next) => {
// get the upload config obj
const upload = uploadConfiguration(dest, whitelist)
// call the upload.single
upload.single(name)(req, res, next)
}
}
// waitForDelay
module.exports = (dest, whitelist, name = 'file') => {
return async (req, res, next) => {
// make sur we wait for the upload to finish to solve the req.file is undefined
await multerDelay()
next()
}
}
router.patch('/profile-picture',
[
AsyncErrorWrapper(passport.verifyJwt()),
AsyncErrorWrapper(singleFileUpload('/images/', ['image/png', 'image/jpeg'])),
AsyncErrorWrapper(waitForDelay()),
], AsyncErrorWrapper(userController.updateProfilePicture))
^ untested code