如何处理没有快递的 multipart/form-data 请求

How to Handle multipart/form-data request without express

所以我有这个表格:

  <form id="myForm" enctype="multipart/form-data">
      <input id="name" title="name" type="text" placeholder="name" />
      <input id="quantity" title="quantity" type="text" placeholder="quantity" />
      <input id="price" title="price" type="text" placeholder="price" />
      <input id="imageLocation" title="imageLocation" type="text" placeholder="imagelocation" />
      <input id="description" title="description" type="text" placeholder="description" />
  </form>

这是我发送数据的地方:

 function postMultiPartHttpCall() {
    var XHR = new XMLHttpRequest();

    var form = document.getElementById("myForm");

    var FD = new FormData(form);

    XHR.addEventListener("load", function (event) {
        var callingObj = {};
        callingObj.responseText = event.target.responseText;
        console.log(callingObj);
    });

    XHR.open("POST", '/articlePost');
    XHR.send(FD);
}

这是我收到它的地方:

    function _processFormData (request, res, onSuccess,onError) {
    var requestBody = '';
    request.on('data', function (data) {
        requestBody += data;
        if (requestBody.length > 1e7) {
            res.writeHead(413, 'Request length too long', { 'Content-Type': 'text/html' });
            res.end('413 : Request Entity Too Large');
        }
    });

    request.on('end', function () {
        var oFormData = qsLib.parse(requestBody);
        console.log(request.headers);

    });
}

所以当我发送一些数据时,我收到了这个 (console.log):

Debugger listening on 127.0.0.1:5858
Server was started
{ host: 'localhost:1337',
connection: 'keep-alive',
'content-length': '44',
origin: 'http://localhost:1337',
'user-agent': 'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36     (KHTML, like Gecko) Chrome/58.0.3029.110 Safari/537.36',
'content-type': 'multipart/form-data; boundary=----WebKitFormBoundaryyVFw7KZwIaAIQeQ1',
accept: '*/*',
referer: 'http://localhost:1337/CartSPA.html',
'accept-encoding': 'gzip, deflate, br',
'accept-language': 'en-US,en;q=0.8,hr;q=0.6,de-AT;q=0.4,de;q=0.2,de-DE;q=0.2' }

所以我想要的是在不使用 expressJS 或其他类似的 3rd 方库的情况下获取具有表单字段的对象。是否可以使用边界编号获取属性,或者我在哪里可以看到发送了哪些数据?

使用https://github.com/felixge/node-formidable:

var formidable = require('formidable'),
    http = require('http'),
    util = require('util');

http.createServer(function(req, res) {
  if (req.url == '/upload' && req.method.toLowerCase() == 'post') {
    // parse a file upload
    var form = new formidable.IncomingForm();

    form.parse(req, function(err, fields, files) {
      res.writeHead(200, {'content-type': 'text/plain'});
      res.write('received upload:\n\n');
      res.end(util.inspect({fields: fields, files: files}));
    });

    return;
  }

  // show a file upload form
  res.writeHead(200, {'content-type': 'text/html'});
  res.end(
    '<form action="/upload" enctype="multipart/form-data" method="post">'+
    '<input type="text" name="title"><br>'+
    '<input type="file" name="upload" multiple="multiple"><br>'+
    '<input type="submit" value="Upload">'+
    '</form>'
  );
}).listen(8080);

我一直在使用 npm 模块 multiparty。这很简单。

在您的请求处理程序中,执行类似这样的操作。

var form = new multiparty.Form();
form.parse(req, function(err, fields, files) {
  res.writeHead(200, {'content-type': 'text/plain'});
  res.write('received upload:\n\n');
  res.end(util.inspect({fields: fields, files: files}));
});

是的,“可以使用边界编号”获取属性,但您必须匹配字段并手动解析名称...

此外,为了发送表单中的值,属性 name needs to be set on the input tags。例如:

<input id="quantity" title="quantity" type="text" placeholder="quantity" />

应更新为包含 name 属性,如下所示:

<input name="quantity" id="quantity" title="quantity" type="text" placeholder="quantity" />

在表单字段上设置名称属性后,请求的 body 应包含表单数据(即 requestBody 应在数据完成时包含编码表单的内容正在加载)。例如,它可能类似于下面的输出:

-----------------------------150182554619156
Content-Disposition: form-data; name="name"

z4520
-----------------------------150182554619156
Content-Disposition: form-data; name="quantity"

2
-----------------------------150182554619156
Content-Disposition: form-data; name="price"

32.90
-----------------------------150182554619156
Content-Disposition: form-data; name="imagelocation"

/img/z4520.jpg
-----------------------------150182554619156
Content-Disposition: form-data; name="description"

water filter
-----------------------------150182554619156--

###解析表单字段

在下面的起始代码中,它检查请求 header Content-Type 边界(你可能还想确保 Content-Type 实际上是“multipart/form-data”)使用 String.indexOf() and then sets the boundary using String.split() and taking the 2nd element from the resultant array. That boundary value can be used to separate the body data into an array (also using String.split()).

我将把它留作 reader 的练习,以解析出值并将它们存储在数组中(参见 @TODO; )。

提示: Array.reduce() 可能会派上用场...

request.on('end', function() {
    if (request.headers.hasOwnProperty('content-type') && request.headers['content-type'].indexOf('boundary=') > -1) {
        var parts = request.headers['content-type'].split('boundary=');
        var boundary = parts[1];
        var splitBody = requestBody.split(boundary);
        /**
         @TODO: iterate over elements in splitBody, matching name and value and add to array of fields
        */

        res.writeHead(200, {"Content-Type": "application/json"});
        res.write(JSON.stringify({formFields: splitBody}));
    }
    else {
        //bad request
        res.writeHead(400, {"Content-Type": "application/json"});
        res.write("missing boundary in content-type"));
    }
    res.end();
});