Nodejs imitate multipart form implementation file upload

Source: Internet
Author: User
Tags foreach


Sometimes there is such a demand, nodejs do webserver, upload files from the browser to the back-end server, node layer just do a data relay, if in this process, node webserver need to make appropriate data processing, and then post to the back end, Then you have to upload the file at the node layer.

First of all, upload files through the browser, the PostData format is a look like:


For example, each set of data is separated by "-----webkitformboundary ..." and ends with this delimiter, and the delimiter is completely customizable.
Each paragraph submits the data, by Content-disposition to describe, does not specify the Content-type, then the default Text/plain, if is uploads the binary file, specifies its mime-type can.
Simple encapsulation of a method to implement the node layer file upload:

/**
* Upload File
* @param files that have been processed by formidable
* @param req HttpRequest objects
* @param additional data submitted by PostData
*/
function UploadFile (Files, req, postdata) {
var boundarykey = Math.random (). toString (16);
var enddata = ' \ r \ n----' + Boundarykey + '-';
var fileslength = 0, content;

Initial data, carry the data from the post back up
Content = (function (obj) {
var rslt = [];
Object.keys (obj). ForEach (function (key) {
arr = [' \ r \ n----' + Boundarykey + ' \ r \ n '];
Arr.push (' Content-disposition:form-data; name= "' + key + '" \r\n\r\n ');
Arr.push (Obj[key]);
Rslt.push (Arr.join ('));
});
Return Rslt.join (");
}) (PostData);

Assemble data
Object.keys (Files). ForEach (function (key) {
if (!files.hasownproperty (key)) {
Delete Files.key;
Return
}
Content = = ' \ r \ n----' + Boundarykey + ' \ r \ n ' +
' content-type:application/octet-stream\r\n ' +
' Content-disposition:form-data; Name= "' + key + '";
' Filename= ' + files[key].name + ' "; \ r \ n ' +
' content-transfer-encoding:binary\r\n\r\n ';
Files[key].contentbinary = new Buffer (content, ' utf-8 ');
Fileslength + + files[key].contentbinary.length + fs.statsync (files[key].path). Size;
});

Req.setheader (' Content-type ', ' multipart/form-data; boundary=--' + Boundarykey);
Req.setheader (' content-length ', Fileslength + buffer.bytelength (enddata));

Perform an upload
var allfiles = Object.keys (files);
var filenum = allfiles.length;
var uploadedcount = 0;
Allfiles.foreach (function (key) {
Req.write (files[key].contentbinary);
var fileStream = Fs.createreadstream (Files[key].path, {buffersize:4 * 1024});
Filestream.on (' End ', function () {
After uploading a successful file, delete the temporary file.
Fs.unlink (Files[key].path);
uploadedcount++;
if (Uploadedcount = = FileNum) {
If it's the last file, it ends normally.
Req.end (Enddata);
}
});
Filestream.pipe (req, {end:false});
});
}

The idea is, the code is not complicated, and it may be extra attention that In http.request response processing, response.headers may be gzip, this time the buffer can not be directly ToString, need to pass zlib decoding and then converted to string, presumably thinking:

var result = [];
Response.on (' Data ', function (chunk) {
Result.push (chunk);
});

Handling response
var _dealresponse = function (data) {
var buffer = data;
try {
data = data.tostring (' UTF8 ');
data = data? (Json.parse (data) | | data): false;
} catch (Err) {
Interface returned data format exception, parsing failed
Console.log (ERR);
}

Self.res.writeHead (Response.statuscode, ' OK ', {
' Content-type ': ' Text/plain; Charset=utf-8 ',
' Content-length ': buffer.length
});
Self.res.write (buffer);
Self.res.end ();
};

Response.on (' end '), function () {
    result = Buffer.concat (result);
   // Gzip data that requires zlib decoding
    if (response.headers[' content-encoding '] = = ' gzip ') {
   & nbsp;    zlib.gunzip (result, function (err, dezipped) {
             var data = err? New Buffer (' {} '): dezipped;
            _dealresponse (data);
       });
   } else {
        _dealresponse (result);
    }
});
Mark, maybe you just need to pass by.

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.