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

使用AJAX、Node/Express及MongoDB(Mongoose)提交表单,内容未存储

问题分析与修复方案

看起来你遇到的核心问题是表单内容没能正确存入MongoDB,同时服务器的请求处理流程也存在一些小问题,咱们一步步拆解解决:

1. 服务器中间件顺序错误,导致API路由无法生效

你的server.js里,那个没有指定路径的app.use(function (req, res) {...})中间件会拦截所有进来的请求——包括你后续定义的/api/clicks路由。因为Express中间件是按顺序执行的,这个通用中间件在routes(app)之前,导致请求还没到达你的API路由就被处理并返回了,这其实会让clickHandler.addClick根本不会被触发(你说控制台输出了saved!可能是测试时的临时情况,先把这个顺序问题修正)。

修改后的server.js:

var express=require('express')
var bodyParser=require("body-parser")
var routes=require('./app/routes/index.js')
var mongoose=require('mongoose')
var app=express()

// 先解析请求体
app.use(bodyParser.urlencoded({ extended: false }))

// 先挂载API路由
routes(app)

// 再处理未匹配到API的请求(比如根路径)
app.use(function (req, res) {
  res.setHeader('Content-Type', 'text/plain')
  res.write('you posted:\n')
  res.end(JSON.stringify(req.body, null, 2))
})

mongoose.connect(/* 你的MongoDB连接字符串 */)
app.listen(3000)

2. AJAX请求的Content-Type设置错误

你用了FormData却手动设置了Content-Type: application/x-www-form-urlencoded,这会导致bodyParser无法正确解析表单数据。FormData默认应该使用multipart/form-data类型,而且不需要手动设置——浏览器会自动添加包含boundary的正确Content-Type。

修改AJAX脚本,删掉错误的请求头设置:

<script>
(function(){
  var xhr;
  var data=document.getElementById('myForm');
  data.addEventListener('submit',makeRequest);
  function makeRequest(e){
    e.preventDefault();
    var formData=new FormData(data);
    xhr= new XMLHttpRequest()
    xhr.onreadystatechange=function(){
      if (xhr.readyState === 4 && xhr.status===200) {
        console.log(xhr.response)
      }
    };
    xhr.open('POST','/api/clicks',true);
    // 删掉这行错误的请求头设置
    // xhr.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');
    xhr.send(formData);
  }
})()
</script>

3. 控制器里的参数冲突与字段获取错误

你的addClick方法里,回调函数的参数用了res——这和路由传入的响应对象res重名了,会覆盖掉原本的响应对象。另外,你直接把req.body传给create,但你的Clicks模型定义的是text字段,而表单里的输入框name是message,所以应该取req.body.message。

修改后的clickHandler.server.js:

function clickHandler(){
  this.addClick=function(req,res){
    // 把回调里的res改成doc,避免和路由的响应对象冲突
    Clicks.create({text: req.body.message}, function (err, doc) {
      if (err) {
        console.error(err);
        // 给客户端返回错误响应
        return res.status(500).json({error: 'Failed to save content'});
      }
      console.log("saved!")
      // 给客户端返回成功响应
      res.status(200).json({success: true, data: doc});
    })
  }
}

4. 补充:解析multipart/form-data类型请求

默认的bodyParser.urlencoded无法解析multipart/form-data类型的请求体,你需要安装multer中间件来处理:

先安装依赖:

npm install multer

然后在server.js里配置:

var multer = require('multer');
// 用内存存储处理文本表单数据
var upload = multer({ storage: multer.memoryStorage() });

// 在挂载路由前,给/api/clicks添加multer中间件(只处理文本字段)
app.use('/api/clicks', upload.none());

验证修改后的流程

  1. 表单提交时,AJAX发送正确的multipart/form-data请求
  2. 服务器先通过multer解析请求体,再到达/api/clicks路由
  3. addClick正确获取req.body.message,存入MongoDB的text字段
  4. 客户端收到成功响应,控制台能看到返回的文档数据

这样就能让表单文本内容正确存入MongoDB了。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.15 03:25:02