Reputation:
So I have this form:
<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>
Here Is where I send the data:
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);
}
And here is where I receive it:
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);
});
}
So when I send some data I receive this (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' }
So what I want is to get an object with the fields of form without using expressJS or other similar 3rd party libraries. Is it possible to get the attributes using the boundary number or where can I see which data was sent?
Upvotes: 4
Views: 4327
Reputation: 8297
Yes it is "possible to get the attributes using the boundary number", though you will have to match the fields and parse out the names manually...
Also, in order to have the values from the form get sent, the attribute name needs to be set on the input tags. For example:
<input id="quantity" title="quantity" type="text" placeholder="quantity" />
Should be updated to contain a name attribute, like below:
<input name="quantity" id="quantity" title="quantity" type="text" placeholder="quantity" />
With the name attributes set on the form fields, the body of the request should contain the form data (i.e. requestBody
should then have the contents of the encoded form when the data is done being loaded). For example, it may look similar to the output below:
-----------------------------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--
###Parsing out the form fields
In the starter code below, it checks the request header Content-Type for the boundary (you might also want to ensure the Content-Type is in fact "multipart/form-data") using 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()).
I will leave it as an exercise for the reader to parse out the values and store them in an array (see @TODO
; ).
Hint: Array.reduce() might come in very handy...
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();
});
Upvotes: 6
Reputation: 581
I have been using the npm module multiparty. It is pretty straight forward.
In your request handler, do something like this.
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}));
});
Upvotes: 0
Reputation: 4804
Use 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);
Upvotes: 0