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

Zag*_*gen 7 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>
Run Code Online (Sandbox Code Playgroud)

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

{
 status: 'published',
 entries: [
   {title: 'Entry 1', content: 'Entry 1 Content...'},
   {title: 'Entry 2', content: 'Entry 2 Content...'}
 ]
}
Run Code Online (Sandbox Code Playgroud)

现在打电话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'
}
Run Code Online (Sandbox Code Playgroud)

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

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

通过Javascript发送原始内容不是一个选项(除非是不可能的),正如在这个问题的第三个答案中所建议的那样: Sailsjs中是否有可能构建更复杂的模型 这样做,至少对于我得到的基于文本的字段正确的输出,不确定图像,因为我已经通过邮差用rawdata测试.

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

bodyParser: {
   fn: require('body-parser').urlencoded,
   options: {extended:true}
 }
Run Code Online (Sandbox Code Playgroud)

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

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

var URLEncodedBodyParser = connect.urlencoded({extended:true})
Run Code Online (Sandbox Code Playgroud)

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

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

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

config/http.js

middleware: {  
     order: [
      // some middleware
      'bodyParser',
      'qsBodyParser',
      // more middleware
    ],
    qsBodyParser: require('../api/middleware/qsBodyParser')
}
Run Code Online (Sandbox Code Playgroud)

并在 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;
Run Code Online (Sandbox Code Playgroud)

rob*_*lep 6

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

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

{
  "entries" : [{
    "content" : "Entry 1 Content..."
  }, {
    "content" : "Entry 2 Content..."
  }]
}
Run Code Online (Sandbox Code Playgroud)

最新版本(body-parser@1.13.3)按预期工作,所以你必须以skipper某种方式插入它.

编辑:这个评论似乎表明,使用multipart/form-data将完全禁用数组(/ object?)解析.

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

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...' } ] }
Run Code Online (Sandbox Code Playgroud)