You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.13 01:05:18