如何通过sails.js中的表单发送数组/对象(使用enctype multipart / form-data)

时间:2015-08-13 03:38:34

标签: javascript node.js express sails.js

我在我的表单中嵌套信息以匹配我的模型,这大大简化了后端的内容,但我无法找到如何在Sails.js中获取数组或对象(或两者的组合)

假设我有一个这样的表格

注意:完全需要支持“multipart / form-data”。

<form action="/articles" method="post" enctype="multipart/form-data">
    <input type="file" name="status" value="published">
    <!-- Entry 0 -->
    <input(type="text" name="entries[0][title]" value="Entry 1")
    <input(type="text" name="entries[0][content]" value="Entry 1 Content...")
    <!-- Entry 1 -->
    <input(type="text" name="entries[1][title]" value="Entry 2")
    <input(type="text" name="entries[1][content]" value="Entry 2 Content...")
    <!-- images -->
    <input type="file" name="images[]">
    <input type="file" name="images[]">
</form>

我希望在req.params.all()obj中获得这样的对象

{
 status: 'published',
 entries: [
   {title: 'Entry 1', content: 'Entry 1 Content...'},
   {title: 'Entry 2', content: 'Entry 2 Content...'}
 ]
}

现在,在调用req.params.all() / req.body时,我得到的是:

{
 status: 'published',
 'entries[0][title]': 'Entry 1'
 'entries[0][content]': 'Entry 1 Content...'
 'entries[1][title]': 'Entry 2'
 'entries[1][content]': 'Entry 2 Content...'
 'entries[0][title]': 'Entry 1'
}

调用req.file('images[]')会给出正确的行为。我正在检查该fn返回的._files属性,并在那里显示我的2张图像。 在这里使用括号似乎很奇怪,但这就是它。

我猜这与我在req.params.all()中获得的内容有关。我可以进一步解析这个问题,但如果将来发生变化,那将会是hacky和脆弱的。在任何情况下,这是任何Web应用程序中的常见模式,并且受到许多语言和框架的支持,所以对我来说真的很奇怪,只需简单的sails.js功能就无法获得我需要的东西,所以我猜我我没有做任何应该做的事情,或者我错过了什么。 请指出我正确的方向,如果Sails实际上不支持这种基本的嵌套行为,那我该怎么办?

通过Javascript发送原始内容不是一个选项(除非是不可能的),如本问题的第三个答案所示: Is it possible in Sailsjs to build more complex models 这样做,至少对于基于文本的字段,我得到正确的输出,不确定图像,因为我已经使用rawdata通过postman进行测试。

修改 到目前为止,我已尝试更改config / http.js中的skipper body解析器,如下所示:

bodyParser: {
   fn: require('body-parser').urlencoded,
   options: {extended:true}
 }

但这使得我的服务器无用,它确实启动了,但它没有响应任何请求,不知道为什么(即使使用他们的自己的示例与船长,你只需要取消注释,不起作用)。

由于skipper基于bodyparser,我修改了skipper模块index.js只是为了测试会发生什么。

var URLEncodedBodyParser = connect.urlencoded({extended:true})

但它没有用,我得到的结果与开头相同,甚至安装了body-parser并使用它而不是connect.urlencoded的body解析器没有效果。

编辑2:由于@robertklep声明使用没有多部分工作的表单数据,但当然我失去了上传文件的能力,这非常重要,我把它放在示例表单中的原因

编辑3:只是为了补充已接受的答案以防有人需要,这就是我所做的:

config/http.js

middleware: {  
     order: [
      // some middleware
      'bodyParser',
      'qsBodyParser',
      // more middleware
    ],
    qsBodyParser: require('../api/middleware/qsBodyParser')
}

并在api/middleware/qsBodyParser

Qs = require('qs');

qsBodyParser = function(req, res, next) {
  if req.is('multipart/form-data'){
   req.body = Qs.parse(req.body);
  }
  return next();
};

module.exports = qsBodyParser;

1 个答案:

答案 0 :(得分:6)

skipper的当前版本取决于connect@2.25.0,这取决于body-parser@1.6.0,它不会处理您发送表单数组/对象的方式。

您的表单示例如下(使用extended : true):

{
  "entries" : [{
    "content" : "Entry 1 Content..."
  }, {
    "content" : "Entry 2 Content..."
  }]
}

最新版本(body-parser@1.13.3)按预期工作,因此您必须以某种方式将其插入skipper

编辑this comment似乎建议使用multipart/form-data将完全禁用数组(/ object?)解析。

编辑#2 :您可以使用qs手动解析req.body,{{3}}似乎接受一个对象作为参数:

var qs  = require('qs');

var obj = qs.parse({
 status: 'published',
 'entries[0][title]': 'Entry 1',
 'entries[0][content]': 'Entry 1 Content...',
 'entries[1][title]': 'Entry 2',
 'entries[1][content]': 'Entry 2 Content...',
});

// obj is now:
// { status: 'published',
//   entries:
//    [ { title: 'Entry 1', content: 'Entry 1 Content...' },
//      { title: 'Entry 2', content: 'Entry 2 Content...' } ] }