MERN电商项目更新产品时无法获取req.body数据求助
问题描述
在MERN电商项目中更新产品时,点击更新按钮无报错,但页面显示旧数据、MongoDB未发生变更;Postman测试同样无报错但返回旧数据。后端控制器打印req.body.name显示undefined。
核心原因与解决方案
1. 后端未配置Multipart数据解析(关键问题)
前端通过FormData发送multipart/form-data类型数据,默认的express.json()中间件无法解析,必须用multer处理文件与文本字段。
修改后端路由配置(示例:productRoutes.js)
import express from 'express'; import { updateproducts } from '../controllers/productController.js'; import multer from 'multer'; import path from 'path'; // 配置multer文件存储 const storage = multer.diskStorage({ destination: (req, file, cb) => { const uploadPath = path.resolve('./uploads'); cb(null, uploadPath); // 确保uploads文件夹存在并有权限 }, filename: (req, file, cb) => { cb(null, `${Date.now()}-${file.originalname}`); // 避免文件名重复 } }); const upload = multer({ storage: storage }); const router = express.Router(); // 用upload.array('images')接收多文件上传,对应前端的FormData.append('images', file) router.put('/update-product/:id', upload.array('images'), updateproducts); export default router;
修改后端控制器
import Category from "../models/categoryModel.js"; import productModel from "../models/productModel.js"; import fs from 'fs'; import path from 'path'; export const updateproducts = async (req, res) => { try { // 现在req.body可获取文本字段,req.files为上传的文件数组 console.log("产品名称: ", req.body.name); // 整理更新数据,仅更新前端传递的字段 const updateData = { name: req.body.name, description: req.body.description, mrp: req.body.mrp, category: req.body.category, InStock: parseInt(req.body.InStock) // 转数字匹配数据库类型 }; // 处理图片逻辑 if (req.files?.length > 0) { // 解析前端传递的删除图片列表,删除服务器文件 if (req.body.DeletedImages) { const deletedImages = JSON.parse(req.body.DeletedImages); deletedImages.forEach(img => { const filePath = path.resolve(`./uploads/${img}`); if (fs.existsSync(filePath)) fs.unlinkSync(filePath); }); } // 合并原有未删除图片与新上传图片 const existingImages = JSON.parse(req.body.existingImages) || []; const newImageNames = req.files.map(file => file.filename); updateData.images = [...existingImages, ...newImageNames]; } // 执行更新,开启runValidators确保字段验证 const product = await productModel.findByIdAndUpdate( req.params.id, updateData, { new: true, runValidators: true } ); if (!product) { return res.status(404).json({ success: false, error: '产品未找到或无法更新' }); } res.json({ success: true, message: '产品更新成功', updatedProduct: product }); } catch (error) { console.error(error); res.status(500).json({ success: false, error: '服务器内部错误' }); } };
2. 前端代码修正
分离原有图片与新上传文件,传递删除列表
// 更新产品函数 const handleUpdate = async (e) => { e.preventDefault(); try { const productData = new FormData(); // 传递文本字段 productData.append("name", name); productData.append("description", description); productData.append("mrp", mrp); productData.append("category", category); productData.append("InStock", InStock); // 传递删除的图片列表(转JSON字符串) productData.append("DeletedImages", JSON.stringify(DeletedImages)); // 分离原有图片(字符串文件名)与新上传文件(File对象) const existingImages = selectedImages.filter(img => typeof img === 'string'); const newImages = selectedImages.filter(img => typeof img !== 'string'); // 传递原有未删除图片 productData.append("existingImages", JSON.stringify(existingImages)); // 仅追加新上传的文件 newImages.forEach(img => productData.append("images", img)); const { data } = await axios.put(`/api/v1/product/update-product/${params.id}`, productData, { headers: { 'Content-Type': 'multipart/form-data' } }); // 修正toast逻辑 if (!data?.success) { toast.error(data?.message); } else { toast.success("产品更新成功"); navigate("/dashboard/manage.vision/admin/products"); } } catch (error) { console.log(error); toast.error("更新失败,请重试"); } };
修复图片预览逻辑(区分原有图片与新上传文件)
{selectedImages && selectedImages.map((image, index) => { const imgSrc = typeof image === 'string' ? `http://localhost:3000/uploads/${image}` : URL.createObjectURL(image); return ( <div key={index} className="image"> <img src={imgSrc} alt="产品图片" className="primg" /> <FontAwesomeIcon icon={faTrashCan} className="prdele" onClick={() => deleteHandler(image)} /> <p className="imgno">{index + 1}</p> </div> ); })}
3. 额外检查项
- 确保后端
uploads文件夹存在且有读写权限 - 验证MongoDB中产品
_id与前端params.id完全一致 - 检查前端下拉选项的
value类型与数据库字段类型匹配(如InStock是数字则传递数字)
内容的提问来源于stack exchange,提问作者Bezelel B
相关产品推荐
相关产品推荐

