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

如何通过Node.js后端上传文件到MySQL数据库并展示照片,解决undefined问题

问题原因
  • 提交数据格式不匹配:前端通过axios直接提交JSON格式数据,未使用multipart/form-data格式,multer仅能解析multipart/form-data类型的请求,无法识别JSON内的文件字段。
  • 文件对象存储错误:文件输入框的onChange回调中仅存储了e.target.value(浏览器返回的虚拟路径字符串),未存储真实的File对象,后端无法获取文件内容。
  • 表单提交逻辑问题:表单提交未阻止默认刷新行为,且axios提交未使用构造好的FormData实例,表单上写的enctype="multipart/form-data"不会自动生效。
  • 多文件字段处理不匹配:存在Photo和UserFP两个文件字段,后端仅配置了upload.single("Photo")处理单个文件,若需要同时上传两个文件需调整multer配置。
修正方案

前端代码修改

  1. 修改文件输入框的onChange逻辑,存储真实File对象,移除文件输入的value属性(受控文件输入不需要绑定value)
  2. 提交时构造FormData对象,所有字段都添加到FormData中
  3. 阻止表单默认提交行为,axios请求头指定正确的格式

关键修改代码:

文件输入部分:

<div className="form-group">
  <label>UserFP</label>
  <input
    type="file"
    className="form-control"
    placeholder="UserFP"
    onChange={(e) => {
      setUserFP(e.target.files[0]); // 存储File对象
    }}
    name="UserFP"
  />
</div>

<div className="form-group">
  <label>Photo</label>
  <input
    type="file"
    className="form-control"
    placeholder="Photo"
    onChange={(e) => {
      setPhoto(e.target.files[0]); // 存储File对象
    }}
    name="Photo"
  />
</div>

表单提交和editData方法部分:

<form onSubmit={(e) => {
  e.preventDefault();
  editData();
}}>
const editData = async () => {
  // 构造FormData
  const formData = new FormData();
  formData.append('CmpnyCode', CmpnyCode);
  formData.append('UserID', UserID);
  formData.append('UserFullName', UserFullName);
  formData.append('UserDetail', UserDetail);
  formData.append('LoginID', LoginID);
  formData.append('Password', Password);
  formData.append('UserPin', UserPin);
  formData.append('UserEmailID', UserEmailID);
  // 文件字段判断:编辑场景下未重新上传文件则传原有旧值
  if (UserFP instanceof File) {
    formData.append('UserFP', UserFP);
  } else {
    formData.append('UserFP', UserFP || '');
  }
  if (Photo instanceof File) {
    formData.append('Photo', Photo);
  } else {
    formData.append('Photo', Photo || '');
  }
  formData.append('IsActive', IsActive);
  formData.append('LicCount', LicCount);
  formData.append('DateCreated', DateCreated);
  formData.append('CreatedBy', CreatedBy);
  formData.append('RecordChanged', RecordChanged);
  formData.append('LocationID', LocationID);
  formData.append('isValid', isValid);
  formData.append('isDeleted', isDeleted);

  await axios.put("http://localhost:8000/upusermst/" + argu, formData, {
    headers: {
      'Content-Type': 'multipart/form-data'
    }
  });
  history.push("/usermst");
};

后端代码修改

如果需要同时接收两个文件,调整multer配置为fields模式,从req.files获取文件对象;如果仅需接收Photo字段的单个文件,保持upload.single("Photo")即可,从req.file获取:

// 方式1:同时接收两个文件字段
app.put("/upusermst/:UserID", upload.fields([{name: 'Photo'}, {name: 'UserFP'}]), (req, res) => {
  const userid = req.params.UserID;
  const CompanyCode = req.body.CmpnyCode;
  const UserID = req.body.UserID;
  const UserFullName = req.body.UserFullName;
  const UserDetail = req.body.UserDetail;
  const LoginID = req.body.LoginID;
  const Password = req.body.Password;
  const UserPin = req.body.UserPin;
  const UserEmailID = req.body.UserEmailID;
  // 有新上传文件就取二进制,没有就用前端传的旧值
  const UserFP = req.files?.UserFP ? req.files.UserFP[0].buffer : req.body.UserFP;
  const Photo = req.files?.Photo ? req.files.Photo[0].buffer : req.body.Photo;
  const IsActive = req.body.IsActive;
  const LicCount = req.body.LicCount;
  const DateCreated = req.body.DateCreated;
  const CreatedBy = req.body.CreatedBy;
  const RecordChanged = req.body.RecordChanged;
  const LocationID = req.body.LocationID;
  const isValid = req.body.isValid;
  const isDeleted = req.body.isDeleted;
  
  console.log('Photo文件:', req.files?.Photo);
  console.log('UserFP文件:', req.files?.UserFP);

  // 数据库操作不变,注意存储二进制的话Photo、UserFP字段类型要设为BLOB/LONGBLOB
  db.query(
    "UPDATE usermst SET CmpnyCode=?,UserID=?,UserFullName=?,UserDetail=?,LoginID=?,Password=?,UserPin=?,UserEmailID=?,UserFP=?,Photo=?,IsActive=?,LicCount=?,DateCreated=?,CreatedBy=?,RecordChanged=?,LocationID=?,isValid=?,isDeleted=? WHERE UserID=?",
    [
      CompanyCode,
      UserID,
      UserFullName,
      UserDetail,
      LoginID,
      Password,
      UserPin,
      UserEmailID,
      UserFP,
      Photo,
      IsActive,
      LicCount,
      DateCreated,
      CreatedBy,
      RecordChanged,
      LocationID,
      isValid,
      isDeleted,
      userid,
    ],
    (err, result) => {
      if (err) {
        console.log(err);
        res.status(500).send(err);
        return;
      }
      res.send(result);
    }
  );
});

如果仅需接收单个Photo文件,multer配置保持upload.single("Photo"),文件获取方式改为:

const Photo2 = req.file;
const Photo = Photo2 ? Photo2.buffer : req.body.Photo;

内容的提问来源于stack exchange,提问作者Chirag Maurya

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.30 21:09:01