有时候就是有这样的需求,Nodejs做网络服务器,从浏览器端上传文件到后端服务器,节点层只是做一个数据中转,如果在这个过程中,节点网络服务器需要对数据进行适当加工,然后再发布到后端,那么就得在节点层模拟文件上传了。
<强>首先,通过浏览器上传文件,PostData格式是长着个样子的:强>
<强>屏幕快照2014-11-22下午9.18.45.png 强>
如图,每一组数据其实就是用“- - - - - -WebkitFormBoundary .....”分隔开的,最后再用这个分隔符结束,而且,这个分隔符完全是可自定义的。
每一段提交数据,则通过附加项来描述,未指定内容类型,则默认文本/平原,如果是上传的二进制文件,指定其mime类型即可。
/* * *上传文件 * @param文件经过强大的处理过的文件 * @param点播httpRequest对象 * @param postData额外提交的数据 */函数还是(文件、点播postData) { var boundaryKey=math . random () .toString (16); var endData=' https://www.yisu.com/r/n---- ' + boundaryKey +“-”; var filesLength=0,内容;//初始数据,把帖子过来的数据都携带上去 内容=(函数(obj) { var rslt=[]; 种(obj)。forEach(函数(关键){ arr=[' \ r \ n - - - - -”+ boundaryKey + ' \ r \ n ']; 加勒比海盗。推动(“附加项:格式;name=" +键+”\ r \ n \ r \ n”); arr.push (obj(例子)); rslt.push (arr.join (")); }); 返回rslt.join (”); })(postData);//组装数据 种(文件)。forEach(函数(关键){ 如果(! files.hasOwnProperty(键)){ 删除files.key; 返回; } 内容+=癨 r \ n - - - - -”+ boundaryKey + + \ r \ n 内容类型:应用程序/八进制\ r \ n”+ “附加项:格式;name=" +键+”;' + 的文件名="[主要]. name + +文件”;\ r \ n ' + “Content-Transfer-Encoding:二进制\ r \ n \ r \ n”; 文件(例子)。contentBinary=new缓冲区(内容、“utf - 8”); (例子).contentBinary filesLength +=文件。(例子).path长度+ fs.statSync(文件).size; }); 要求的事情。setHeader(“内容类型”、“多部分/格式;边界=? + boundaryKey); 要求的事情。setHeader(内容长度,filesLength + Buffer.byteLength (endData));//执行上传 var allFiles=种(文件); var fileNum=allFiles.length; var uploadedCount=0; allFiles。forEach(函数(关键){ (例子).contentBinary req.write(文件); var=fs.createReadStream (fileStream文件(例子)。路径,{bufferSize: 4 * 1024}); 文件流。(“结束”,函数(){//上传成功一个文件之后,把临时文件删了 (例子).path fs.unlink(文件); uploadedCount + +; 如果(uploadedCount==fileNum) {//如果已经是最后一个文件,那就正常结束 req.end (endData); } }); 文件流。管(点播,{结束:假}); }); }
思路就这样,代码也不复杂,可能额外需要注意的是,在http.request的响应处理中,response.headers可能是gzip的,这个时不候缓冲区能直接toString,需要通过zlib解码再转换为字符串,大概思路:
结果var=[]; 响应。(“数据”,函数(块){ result.push(块); });//处理反应 var _dealResponse=function(数据){ var缓冲=数据; 尝试{ data=https://www.yisu.com/zixun/data.toString (use utf8); data=https://www.yisu.com/zixun/data ?(JSON.parse(数据)| |数据):假; }捕捉(err) {//接口返回数据格式异常,解析失败 console.log(错); } self.res.writeHead(响应。statusCode、“OK”{ “内容类型”:“文本/平原;charset=utf - 8 ', 的内容长度:buffer.length }); self.res.write(缓冲); self.res.end (); }; 响应。(“结束”,函数(){ 结果=Buffer.concat(结果);//gzip的数据,需要zlib解码 如果响应。标题(“内容编码”)==gzip) { zlib。gunzip(因此,函数(呃,dezipped) { var=https://www.yisu.com/zixun/err数据?新缓冲区(“{}”):dezipped; _dealResponse(数据); }); 其他}{ _dealResponse(结果); } });
马克一下,也许你路过正好需要~ ~ ~
以上这篇节点层模拟实现多部分表单的文件上传示例就是小编分享给大家的全部内容了,希望能给大家一个参考,也希望大家多多支持。