Multer diskStorage的destination中req.body为undefined,如何传递name?
解决Multer destination中req.body为undefined的问题
问题原因
Multer处理multipart/form-data请求时,会按请求体内容的顺序解析数据:如果文件字段在文本字段之前发送,执行destination函数时文本字段还未被解析到req.body,就会出现undefined的情况。
另外你的代码存在一处错误:req.file.image.originalname写法有误,req.file本身就是上传的文件对象,直接访问req.file.originalname即可。
解决方案
1. 规范前端请求格式与字段顺序
- 前端必须采用
multipart/form-data格式发送请求(不能用application/json); - 将
name、email等文本字段放在文件字段(image)之前发送,确保Multer处理文件时已解析完成文本字段,req.body就能获取到对应值。
2. 修正后端代码
调整代码错误并优化逻辑:
import express from 'express'; import dotenv from 'dotenv'; import { mongoose } from 'mongoose'; import Artist from './src/Models/artistmodel.js'; import cors from 'cors'; import multer from 'multer'; import fs from 'fs'; import path from 'path'; import { fileURLToPath } from 'url'; import { dirname } from 'path'; dotenv.config(); const PORT = process.env.PORT; const app = express(); app.use(cors()) // 注:express.json()和express.urlencoded()对multipart/form-data无效,无需添加 // app.use(json()); // app.use(express.urlencoded({ extended: true })); // 定义__dirname用于路径解析 const __dirname = dirname(fileURLToPath(import.meta.url)); // Multer存储配置 const upload = multer({ storage: multer.diskStorage({ destination: (req, file, cb) => { const { name } = req.body; // 增加参数校验,避免name为空时生成错误路径 if (!name) { return cb(new Error('必须传入name参数')); } // 使用path.join避免路径拼接跨平台问题 const folderPath = path.join(__dirname, 'uploads/artists', name); console.log(folderPath) if (!fs.existsSync(folderPath)) { fs.mkdirSync(folderPath, { recursive: true }); } cb(null, folderPath); }, filename: (req, file, cb) => { cb(null, Date.now() + '-' + file.originalname); } }) }); // 连接数据库 mongoose.connect("mongodb://localhost:27017/Anitify") .then(()=>{ console.log("Connected to Mongodb") }) .catch((err)=>{ console.log("Error connecting to mongodb", err); }) app.post('/registerartist', upload.single('image'), (req, res) => { const { name, email, password, genre } = req.body; // 修正文件信息打印逻辑 console.log("image is", req.file.originalname); console.log("body is", req.body.name); Artist.findOne({ email: email }) .then(result=>{ if(!result){ // 返回创建结果,确保后续then能拿到数据 return Artist.create(req.body); }else{ console.log("already exists"); return null; } }) .then(user=>{ if(user) res.json(user); else res.status(400).json({ message: 'Artist already exists' }); }) .catch((err)=>{ console.log(err); res.status(500).json({ error: err.message }); }) }); app.listen(PORT, () => { console.log(`Server running on port ${PORT}`); });
备选方案(不受前端字段顺序限制)
如果无法控制前端字段顺序,可以将name放在URL参数中,绕过解析顺序问题:
// 修改接口路径 app.post('/registerartist/:name', upload.single('image'), (req, res) => { const name = req.params.name; // 剩余业务逻辑... }); // 在destination中通过req.params.name获取值 destination: (req, file, cb) => { const name = req.params.name; const folderPath = path.join(__dirname, 'uploads/artists', name); // 剩余路径处理逻辑... }
内容的提问来源于stack exchange,提问作者Phantom
相关产品推荐
相关产品推荐

