Node.js+Express环境下如何在multer的upload函数外访问req.file.path的值
问题解决方法
原代码存在隐性语法错误:await关键字用在了未被async修饰的upload回调函数中,运行时会直接报错,需要优先修复
要在upload回调外访问req.file.path赋值的image变量,核心要先解决Multer upload函数的异步执行时序问题,你可以用以下两种方案实现:
方案1:封装Multer为Promise形式(推荐,符合异步编程规范)
将callback形式的upload方法封装为Promise,就可以用await直接拿到上传结果,在后续逻辑里直接访问req.file的返回值:
router.post('/gymcreate',async(req,res) => { let userName = req.body.userName; let gymName = req.body.gymName; let location = req.body.location; let phoneNumber = req.body.phoneNumber; let priceRange = req.body.priceRange; let upload = multer({ storage: storage }).single('profile_pic'); // 封装upload为Promise const uploadPromise = (req, res) => new Promise((resolve, reject) => { upload(req, res, function(err) { if (req.fileValidationError) return reject(req.fileValidationError); else if (!req.file) return reject(new Error('Please select an image to upload')); else if (err instanceof multer.MulterError) return reject(err); else if (err) return reject(err); resolve(req.file.path) }) }) // 这里就可以拿到image变量,在upload逻辑外使用了 let image try { image = await uploadPromise(req, res) } catch (e) { return res.send(e.message) } // 后续数据库操作也不需要嵌套在upload回调里了 try{ const creategym = await gymData.create(userName,gymName,location,phoneNumber,priceRange,image); if(creategym){ res.status(200).redirect('/gyms') } else { res.status(500).render('gymbars/creategym', {title: "Error", error: 'Internal Server Error'}) } } catch(e){ res.sendStatus(500) } })
方案2:顶层声明变量+逻辑触发(不推荐,容易出现时序bug)
如果只是需要变量定义在upload外部,可以先在路由顶层声明变量,等upload回调执行完成后赋值,所有用到image变量的逻辑必须保证在upload回调执行完成后才触发:
router.post('/gymcreate',async(req,res) => { let userName = req.body.userName; let gymName = req.body.gymName; let location = req.body.location; let phoneNumber = req.body.phoneNumber; let priceRange = req.body.priceRange; // 顶层声明image变量 let image let upload = multer({ storage: storage }).single('profile_pic'); upload(req, res, async function(err) { if (req.fileValidationError) { return res.send(req.fileValidationError); } else if (!req.file) { return res.send('Please select an image to upload'); } else if (err instanceof multer.MulterError) { return res.send(err); } else if (err) { return res.send(err); } // 给顶层变量赋值 image = req.file.path; // 触发用到image的后续逻辑 handleDbLogic() }); // 单独抽离的数据库逻辑,这里就可以直接访问外层的image变量 async function handleDbLogic() { try{ const creategym = await gymData.create(userName,gymName,location,phoneNumber,priceRange,image); if(creategym){ res.status(200).redirect('/gyms') } else { res.status(500).render('gymbars/creategym', {title: "Error", error: 'Internal Server Error'}) } } catch(e){ res.sendStatus(500) } } })
注意:不要直接在upload函数调用的下方同步访问image变量,此时upload的异步回调还没执行,image一定是undefined。
内容的提问来源于stack exchange,提问作者Swayam Shah
相关产品推荐
相关产品推荐

