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

Node.js前后端连接异常:前端表单无法正确提交数据

前后端表单提交数据校验失败问题解决方案

问题描述

前端HTML表单提交数据到后端时,Joi校验中间件提示"name" is required,"address" is required,"contact" is required,即后端未接收到前端传递的表单数据,但各部分代码可独立运行,需解决数据传递异常问题。


相关代码展示

控制器代码

const memberModel =require('../models/index').member
const Op = require('sequelize').Op

exports.getAllMember = async (request, response) => {
    let members = await memberModel.findAll()
    return response.json({
        success:true,
        data:members,
        message: 'member ke load'
    })
}

exports.addMember = (request,response) => {
    let newMember = {
        name: request.body.name,
        address: request.body.address,
        gender: request.body.gender,
        contact: request.body.contact
    }

    memberModel.create(newMember)
    .then(result => {
        return response.json({
            success: true,
            data:result,
            message: 'new membruh'
        })
    })
    .catch(error => {
        return response.json({
            success: false,
            message: error.message
        })
    })
}

路由代码

const express = require('express')
const app = express()
app.use(express.json())
const memberController = require('../controllers/member.controller')
let { validateMember } = require(`../middlewares/member-validation`)
app.get("/", memberController.getAllMember)
app.post("/", [validateMember], memberController.addMember)
module.exports = app 

中间件代码

const Joi = require(`joi`)
const validateMember = (request, response, next) => {
    const rules = Joi
    .object()
    .keys({
        name: Joi.string().required(),
        address: Joi.string().required(),
        contact: Joi.number().required(),
        gender: Joi.string().valid(`Male`, `Female`)

    })
    .options({ abortEarly: false})
    let { error } = rules.validate(request.body)
    if (error != null){
        let errMessage = error.details.map( it => it.message).join(",")
        return response.status(422).json({
            success: false,
            message: errMessage
        })
    }
    next()
}
module.exports = {validateMember}

主文件代码

const express = require('express');
const app = express();
const PORT = 8000; // Use uppercase for constant variable
const cors = require('cors');
const bodyParser = require('body-parser'); // Import body-parser

app.use(bodyParser.urlencoded({ extended: true })); // Use body-parser to parse form data
app.use(bodyParser.json()); 
app.use(cors()); // Use app.use() for middleware

const memberRoute = require('./routes/member.route')
app.use('/member', memberRoute)

app.listen(PORT,() => {
    console.log('lezgo 8000')
} )

前端HTML表单代码

<!DOCTYPE html>
<html>
<head>
    <title>Add Member</title>
</head>
<body>
    <h1>Add Member</h1>

    <form id="memberForm" name="memberForm">
        <label for="name">Name:</label>
        <input type="text" id="name" name="name" required><br>

         <label for="gender">Gender:</label>
        <select id="gender" name="gender" required>
            <option value="male">Male</option>
            <option value="female">Female</option>
        </select><br>

        <label for="address">Address:</label>
        <input type="text" id="address" name="address" required><br>

        <label for="contact">Contact:</label>
        <input type="text" id="contact" name="contact" required><br>

        <button type="submit">Submit</button>
    </form>

    <div id="message"></div>

    <script>
        const memberForm = document.getElementById('memberForm');
        const message = document.getElementById('message');

        memberForm.addEventListener('submit', async (e) => {
            e.preventDefault();

            const formData = new FormData(memberForm);

            try {
                const response = await fetch('http://localhost:8000/member', {
                    method: 'POST',
                    body: formData,
                });

                const data = await response.json();

                if (data.success) {
                    message.innerHTML = data.message;
                    memberForm.reset();
                } else {
                    message.innerHTML = data.message;
                }
            } catch (error) {
                message.innerHTML = error.message;
            }
        });
    </script>
</body>
</html>

问题原因分析

  1. 数据格式不匹配:前端用FormData发送multipart/form-data格式数据,但后端仅配置了json和urlencoded格式的解析中间件,无法解析该类型数据,导致request.body为空,触发必填字段缺失的校验错误。
  2. 性别值大小写不匹配:前端下拉框的性别值为小写male/female,但后端Joi校验规则要求的是大写开头的Male/Female,即使数据传递成功也会触发校验失败。

解决方案

方案1:修改前端请求为JSON格式(推荐)

利用后端已配置的express.json()中间件,将表单数据转为JSON格式发送,同时统一性别值格式:

memberForm.addEventListener('submit', async (e) => {
    e.preventDefault();

    // 将表单数据转为JSON对象
    const formData = new FormData(memberForm);
    const payload = Object.fromEntries(formData);
    // 统一性别值为开头大写格式
    payload.gender = payload.gender.charAt(0).toUpperCase() + payload.gender.slice(1);

    try {
        const response = await fetch('http://localhost:8000/member', {
            method: 'POST',
            headers: {
                'Content-Type': 'application/json' // 指定请求格式为JSON
            },
            body: JSON.stringify(payload), // 转为JSON字符串发送
        });

        const data = await response.json();

        if (data.success) {
            message.innerHTML = data.message;
            memberForm.reset();
        } else {
            message.innerHTML = data.message;
        }
    } catch (error) {
        message.innerHTML = error.message;
    }
});

方案2:后端添加multipart/form-data解析中间件

若坚持使用FormData发送数据,需安装并配置multer中间件解析该格式,同时修正性别值匹配问题:

  1. 安装multer:
npm install multer
  1. 修改主文件代码,添加multer配置:
const express = require('express');
const app = express();
const PORT = 8000;
const cors = require('cors');
const bodyParser = require('body-parser');
const multer = require('multer'); // 引入multer
const upload = multer(); // 初始化multer,仅解析字段不存储文件

app.use(bodyParser.urlencoded({ extended: true }));
app.use(bodyParser.json());
app.use(upload.none()); // 解析multipart/form-data格式的普通字段
app.use(cors());

const memberRoute = require('./routes/member.route')
app.use('/member', memberRoute)

app.listen(PORT,() => {
    console.log('lezgo 8000')
} )
  1. 修正性别值匹配:
    • 要么修改前端下拉框的value值:
      <select id="gender" name="gender" required>
          <option value="Male">Male</option>
          <option value="Female">Female</option>
      </select>
      
    • 要么修改后端Joi校验规则:
      gender: Joi.string().valid(`Male`, `Female`, `male`, `female`)
      

内容的提问来源于stack exchange,提问作者Mu Za

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.09 06:41:15