【问题标题】:Changing form type to multipart/form-data causes req.body to be empty将表单类型更改为 multipart/form-data 会导致 req.body 为空
【发布时间】:2014-01-26 22:38:18
【问题描述】:

当我在没有指定enctype 的情况下设置表单时,Firefox 会自动将其设置为application/x-www-form-urlencoded 并且req.body 包含输入到表单中的所有参数的漂亮JSON 表示。但是当我把enctype改成multipart/form-datareq.body突然就空了。

这是我的表格:

<form action="/create" method="post" enctype="multipart/form-data">
  <fieldset>
    <div>
      <label>Category:</label>
    </div>
    <div>
      <select name="category">
      <option value="standard">Standard</option>
      <option value="custom">Custom</option>
    </div>
    <div>
      <input type="text" name="description">
    </div>
    <div>
      <label>User ID:</label>
    </div>
    <div>
      <input type="text" name="userid">
    </div>
    <div>
      <input type="submit" value="Go">
    </div>
  </fieldset>
</form>

enctypemultipart/form-data 并且未指定enctype 时,执行console.log(JSON.stringify(req.body, null, 2)); 会打印出一个空对象,它会打印出如下内容:

{
  category: "standard",
  userid: "foo"
}

发生这种情况有什么原因吗?

【问题讨论】:

    标签: json forms node.js express


    【解决方案1】:

    尝试使用 busboy-body-parser 检索请求正文参数和文件。

    start.js
    var bodyParser = require('body-parser');
    var busboyBodyParser = require('busboy-body-parser');
    
    
    // parse application/x-www-form-urlencoded
    app.use(bodyParser.urlencoded({
      extended: true
    }));
    
    // parse application/json
    app.use(bodyParser.json());
    
    
    //parse multipart/form-data    
    app.use(busboyBodyParser());
    
    
    
    controllers/someController.js
    someAction: function(req,res){
         if(req.method == "POST"){
               res.end(JSON.stringify(req.body)+JSON.stringify(req.files));
         }
    }
    //{"text":"testx"}{"anexo":{"data":{"type":"Buffer","data":.... }}} 
    //req.body = {"text":"testx"}
    //req.files = {"anexo":{"data":{"type":"Buffer","data":.... }}} 
    
    
    views/someController/someAction.html
    <form method="post" id="multipart" enctype="multipart/form-data">
        <input type="text" id="text1" name="text" value="testx" />
        <input type="file" id="anexo" name="anexo"  />
        <input type="submit" value="Enviar" />
    </form>
    

    要创建一个上传的文件,你需要工作如果流,例如:

    /* file props
    {  
       "data":{"type":"Buffer","data":.... },
       "fieldname":"anexo",
       "originalname":"images (1).jpg",
       "encoding":"7bit",
       "mimetype":"image/jpeg",
       "destination":"c:\\live\\sources\\uploads\\",
       "filename":"eventclock_images (1)_1443706175833.jpg",
       "path":"c:\\live\\sources\\uploads\\eventclock_images(1)_1443706175833.jpg",
       "size":9986
    }
    */
    
    var fileStream = fs.createWriteStream(file.path);
    fileStream.write(file.data);
    fileStream.end();
    
    fileStream.on('error', function (err) {
        //console.log("error",err);
    });
    fileStream.on('finish', function (res) {
        //console.log("finish",res);
    });     
    

    【讨论】:

    • 你不应该回答你的情况。考虑提问者的情况。
    • @Anderson,通过使用 busboy-body-parser,我仍然得到一个空的请求正文。
    【解决方案2】:

    听起来您使用的是express.urlencoded() 而不是express.multipart()

    【讨论】:

    • 谢谢。我是 Express 的新手,只是使用标准设置。没有意识到这是需要在 app.js 中更改的内容
    • @robertklep,您可能是正确的(如果没有看到 OPs Express 代码就无法确定),但 express.multipart(实际上是 Connect 中间件)已被弃用,不应使用。请参阅我的答案以获取替代方案。
    • @EthanBrown 我并不完全不同意您的观点,但是 IMO,如果某些内容已被弃用,则应将其删除。只要它仍然可用,我就会使用它。顺便说一句,unstable notices 也是如此。
    • 在这一点上我基本同意你的看法,罗伯特:我希望 Express 能将其删除。但是,对于一个每月下载 50 万次的框架,我从来不需要维护向后兼容性!在这种特定情况下,使用bodyParser 完全等同于使用jsonurlencodedmultipart,按此顺序。对我来说,单独使用这些中间件实际上更清楚。而且由于 Busboy 比 multipart 更强大(而且它有前途),好吧,不使用它似乎很固执。
    【解决方案3】:

    我认为@robertklep 是正确的,但我不同意他的回答。 express.multipart()deprecated and should not be used

    如果您需要多部分表单处理,我强烈推荐Busboy。如果您想了解所有详细信息,请参阅this answer

    【讨论】:

    • stackoverflow.com/questions/19581146/… - 您可以解决弃用通知,该通知将在 Express 使用 Connect 3.0 时修复。
    • 这个答案正是我建议发帖人做的。如果您阅读我引用的答案,它会包含所有详细信息。但是是的:为了避免弃用通知,结果是明确使用jsonurlencoded 而不是使用bodyParser。不过,具体来说,我是说 不要 使用 multipart,它已被弃用,并触及了 OP 答案的核心。
    • 哦!所以你没有看到。好东西。
    • 呃,我本可以更明确一点。感谢您的澄清!
    【解决方案4】:
    npm install multer --save
    
    in main.js
    
    var multer  =   require('multer');
    var upload = multer()
    
    router.route("/quotes").post(upload.array(),function(req, res, next){
            name = req.body.name;
            email = req.body.email;
    }
    

    【讨论】:

    • 在代码中包含一些解释总是一个好主意。
    猜你喜欢
    • 1970-01-01
    • 2017-10-31
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-10-31
    • 2014-08-08
    相关资源
    最近更新 更多