问题
I am writing a code to let the client upload two files on the server. Since I used the director router, I have set a listener like this:
request.chunks = [];
request.on('data', function (chunk) {
request.chunks.push( chunk.toString());
};
and here is the console.log of the chunks when a client uploads a file (based on the browser the boundaries change):
-----------------------------7dd2c419180232
Content-Disposition: form-data; name="filename"
-----------------------------7dd2c419180232
Content-Disposition: form-data; name="uploadfile"; filename="first.txt"
Content-Type: application/octet-stream
the content of first file
-----------------------------7dd2c419180232
Content-Disposition: form-data; name="wfilename"
-----------------------------7dd2c419180232
Content-Disposition: form-data; name="wuploadfile"; filename="second.txt"
Content-Type: application/octet-stream
the content of the second file
-----------------------------7dd2c419180232--
I have handled the problem by a few regular expressions for extracting each file-name and each file-content on the request.chunks
variable, but the browsers have different tendencies (for these boundries, for example for google chrome is like this: '------WebKit...') and I wonder if there is a direct way to parse file-name and file-content (obviously from request.chunks
not request
) with some modules like formidable or multi-part or querystring?
Thanks to @micnic, I came up with a parser for the headers. It may need revisions which are welcome at this level:
exports.parseMultipart = function(request) {
// Convert the chunks to string
var str = request.chunks.toString();
// Get the boundry out pf header
var boundry = '--' + request.headers["content-type"].substring(request.headers["content-type"].indexOf('=')+1, request.headers["content-type"].length);
// Initialization
var request_data = {};
index = 0;
// For each form element, store the value in request_data
while (str.indexOf(boundry, index) != -1) {
index += boundry.length;
i = str.indexOf(" name=\"",index);
j = str.indexOf("\"",i+7);
name = str.substring(i+7,j);
var value = {};
if (str.charAt(j+1)==';') {
value["type"] = "file";
i = j + 3;
j = str.indexOf("\"",i+14);
filename = str.substring(i+10, j);
value["filename"] = filename;
i = j + 17;
j = str.indexOf("\r", i);
contentType = str.substring(i, j);
value["content-type"] = contentType;
i = j + 4;
j = str.indexOf("\n\r\n" + boundry, i);
fileContent = str.substring(i, j);
value["content"] = fileContent;
} else {
value["type"] = "field";
i = j + 5;
j = str.indexOf("\r\n" + boundry,i);
value["content"] = str.substring(i,j);
}
index = str.indexOf(boundry, index) + 2;
request_data[name] = value;
}
return request_data;
}
回答1:
For my module simpleS I wrote a parser: https://github.com/micnic/simpleS/blob/ccc8e600013da70d5204c1b66149e834d2c0fea2/utils/utils.js#L365
May be it's a bit difficult to understand it, but it does the work.
"... I wonder if there is a direct way to parse file-name and file-content with some modules like formidable or multi-part or querystring? ...", did you read formidable's docs?
from there:
var formidable = require('formidable');
/* ... */
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}));
});
/* ... */
来源:https://stackoverflow.com/questions/16685895/how-to-handle-form-data-in-an-http-requests-in-nodejs