使用Multer上传图片时自定义创建目录后文件无法保存问题求助
问题根源
- 异步执行顺序错误:
destination配置中的fs.access及目录创建逻辑为异步操作,你未等待目录创建完成就直接调用了存储路径回调,Multer 执行文件写入时对应目录还未生成,导致文件写入失败。同时你将async关键字写在了fs.access的回调函数中,外层逻辑并不会等待该异步任务执行完成。 - 冗余的目录校验逻辑:
fs.promises.mkdir开启recursive: true配置后会自动兼容已存在的目录,不需要提前通过fs.access判断目录是否存在,反而增加了异步逻辑复杂度。
修复方案
直接重写 destination 逻辑,等待目录创建完成后再调用回调返回存储路径即可,修复后的完整代码如下:
const storage = multer.diskStorage({ destination: async function(request, file, callback) { let userUploadDir = uploadDir + '/' + request.body.user + '/' + request.body.address; try { // 直接创建目录,recursive配置自动兼容已存在目录 await fs.promises.mkdir(userUploadDir, { recursive: true }); // 目录创建完成后再返回路径 callback(null, userUploadDir); } catch (err) { callback(err); } }, filename: function(request, file, callback) { let date = new Date(); // 原代码getMonth()返回值从0开始,此处+1修正月份显示 let stringDate = date.getFullYear() + "-" + (date.getMonth() + 1) + "-" + date.getDate() + "-" + date.getHours() + "-" + date.getMinutes(); let newFileName = stringDate + "-" + file.originalname; callback(null, newFileName); }, fileFilter: function(request, file, callback) { let ext = path.extname(file.originalname).toLowerCase(); // 增加toLowerCase兼容大写后缀的图片,比如.PNG if (ext !== ".png" && ext !== ".jpg" && ext !== ".jpeg" && ext !== ".webp") { return callback(new Error("Only images are allowed")); } callback(null, true); } }); const upload = multer({ storage: storage, limits: { fileSize: 1024 * 1024 * 5 } }); router.post("/image", upload.fields([{ name: 'file', maxCount: 3 }]), async (request, response, next) => { response.json({ "message":"Successful file uploaded." }) })
额外注意事项
- 前端提交 FormData 时,请保证
user、address普通字段的添加顺序在file文件字段之前,Multer 按表单字段顺序解析,若文件字段在前,解析到文件时request.body还未拿到普通字段值,会导致目录生成错误。 - 可根据自身需求决定是否保留月份修正、大小写后缀兼容的调整。
内容的提问来源于stack exchange,提问作者Nextrati
相关产品推荐
相关产品推荐

