React+Node使用Multer时,未传图片提交表单出现路径未定义错误
问题描述
我用React+Node,通过Multer实现图片上传到数据库的功能,正常上传时没问题。现在需要支持不上传图片也能提交表单,展示时用默认图片,但目前不上传图片就会报错,后端product.controller.js里直接取req.file.path导致报错,求解决。
现有代码
React 前端代码
const [data, setData] = useState({ pSellingPrice: "", pImage: "", }) const inputImgs = useRef(); const handleSubmit = (e) => { e.preventDefault(); let getRandomKey = Math.floor(Math.random() * 19999999); //Insert data to database const formData = new FormData(); formData.append("pImage", inputImgs.current.files[0]); Object.entries(data).forEach(([key, value]) => formData.append(key, value)); formData.append("pId", getRandomKey); formData.append("pIsActive", 1); //Post api axios .post( "http://localhost:4000/api/products/product/addProduct", formData, { headers: { "Content-Type": "multipart/form-data", }, }, { headers: { "Content-type": "application/json" }, } ) .then((res) => { console.log(res) }) .catch((err) => { console.log(err); }); };
表单部分
<form onSubmit={(e)=>{handleSubmit(e)}}> <input type="number" className="form-control" id="formrow-inputZip" name="pSellingPrice" value={data.pSellingPrice} onChange={(e) => { handleChange(e); }} required /> <div className="col-md-6"> <div class="mb-3"> <label for="formFile" class="form-label"> 选择产品图片 </label> <input class="form-control" ref={inputImgs} type="file" id="formFile" name="pImage" /> </div> </div> </form>
Node 后端代码
product.Router.js
const {createProduct} = require("./Product.controller"); const router = require("express").Router(); const cors = require("cors"); const multer = require("multer"); const path = require("path"); const storage = multer.diskStorage({ destination: "./image/productImage", filename: function (req, file, cb) { cb(null, "IMAGE-" + Date.now() + path.extname(file.originalname)); }, }); const upload = multer({ storage: storage, }).single("pImage"); router.post("/addProduct", upload, createProduct); module.exports = router;
product.Controller.js
const path = require("path"); const {addProduct}= = require("./product.service"); // 语法错误:多了一个= module.exports = { createProduct: (req, res) => { console.log(req.body); const body = req.body; let image = req.file.path; // 无图片时req.file为null,此处直接取值报错 console.log(image + "img"); image = image.replace("\", "\\"); // 转义写法错误 body.pImage = image; console.log(body.pImage); addProduct(body, (err, results) => { if (err) { console.log(err); return res.status(500).json({ success: 0, message: "数据库连接错误", }); } return res.status(200).json({ success: 1, data: results, }); }); }, }
product.service.js
const pool = require("../../../config/database"); module.exports = { addProduct: (data, callBack) => { console.log(data); const query = `INSERT INTO products (pSellingPrice,pImage) VALUES ('${data.pSellingPrice}' ,'${data.pImage.slice(19)}')`; console.log(query); pool.query(query, (error, results, fields) => { if (error) { console.log(error); return callBack(error); } return callBack(null, results); }); }, }
解决方案
1. 前端修改
- 提交表单时判断是否选择了图片,仅在有文件时添加到FormData,避免传入undefined
- 修复axios的headers参数错误(无需传两个headers对象,
multipart/form-data足够)
修改后的handleSubmit:
const handleSubmit = (e) => { e.preventDefault(); let getRandomKey = Math.floor(Math.random() * 19999999); const formData = new FormData(); // 仅当选择了文件时才添加到formData if (inputImgs.current.files.length > 0) { formData.append("pImage", inputImgs.current.files[0]); } Object.entries(data).forEach(([key, value]) => formData.append(key, value)); formData.append("pId", getRandomKey); formData.append("pIsActive", 1); axios .post( "http://localhost:4000/api/products/product/addProduct", formData, { headers: { "Content-Type": "multipart/form-data", }, } ) .then((res) => { console.log(res) }) .catch((err) => { console.log(err); }); };
2. 后端修改
- 修复controller里的语法错误(去掉多余的
=) - 判断
req.file是否存在,不存在则设置默认图片路径 - 用path模块处理路径,避免手动转义错误
修改后的product.Controller.js:
const path = require("path"); const { addProduct } = require("./product.service"); // 修复语法错误 module.exports = { createProduct: (req, res) => { console.log(req.body); const body = req.body; let image; // 判断是否上传了图片 if (req.file) { // 用path模块处理路径,避免转义问题 image = path.join(req.file.path); // 统一转成正斜杠(根据你的存储需求调整) image = image.replace(/\\/g, "/"); } else { // 设置默认图片路径,根据你的项目实际路径调整 image = "/image/productImage/default.jpg"; // 也可以存标识,前端展示时判断用默认图:image = "default" } body.pImage = image; console.log(body.pImage); addProduct(body, (err, results) => { if (err) { console.log(err); return res.status(500).json({ success: 0, message: "数据库操作错误", }); } return res.status(200).json({ success: 1, data: results, }); }); }, }
3. 数据库适配
如果数据库pImage字段不允许为空,确保默认路径有效;若允许为空,前端展示时判断字段值,为空则加载默认图片。
内容的提问来源于stack exchange,提问作者programming Digital
相关产品推荐
相关产品推荐

