Node层模拟实现multipart表单的文件上传示例


Posted in Javascript onJanuary 02, 2018

有时候就是有这样的需求,Nodejs做webserver,从浏览器端上传文件到后端服务器,Node层只是做一个数据中转,如果在这个过程中,Node webserver需要对数据进行适当加工,然后再Post到后端,那么就得在Node层模拟文件上传了。

首先,通过浏览器上传文件,PostData格式是长着个样子的:

Node层模拟实现multipart表单的文件上传示例

屏幕快照 2014-11-22 下午9.18.45.png

如图,每一组数据其实就是用“-----WebkitFormBoundary.....”分隔开的,最后再用这个分隔符结束,而且,这个分隔符完全是可自定义的。

每一段提交数据,则通过Content-Disposition来描述,未指定Content-Type,则默认text/plain,如果是上传的二进制文件,指定其mime-type即可。

简单封装一个方法,实现Node层的文件上传:

/**
 * 上传文件
 * @param files  经过formidable处理过的文件
 * @param req  httpRequest对象
 * @param postData 额外提交的数据
 */
function uploadFile(files, req, postData) {
 var boundaryKey = Math.random().toString(16);
 var endData = '\r\n----' + boundaryKey + '--';
 var filesLength = 0, content;

 // 初始数据,把post过来的数据都携带上去
 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);

 // 组装数据
 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));

 // 执行上传
 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 () {
   // 上传成功一个文件之后,把临时文件删了
   fs.unlink(files[key].path);
   uploadedCount++;
   if (uploadedCount == fileNum) {
    // 如果已经是最后一个文件,那就正常结束
    req.end(endData);
   }
  });
  fileStream.pipe(req, {end: false});
 });
}

思路就这样,代码也不复杂,可能额外需要注意的是,在http.request的response处理中,response.headers可能是gzip的,这个时候buffer不能直接toString,需要通过zlib解码再转换为string,大概思路:

var result = [];
response.on('data', function (chunk) {
 result.push(chunk);
});

// 处理response
var _dealResponse = function (data) {
 var buffer = data;
 try {
  data = data.toString('utf8');
  data = data ? (JSON.parse(data) || data) : false;
 } catch (err) {
  // 接口返回数据格式异常,解析失败
  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 的数据,需要zlib解码
 if (response.headers['content-encoding'] == 'gzip') {
  zlib.gunzip(result, function (err, dezipped) {
   var data = err ? new Buffer('{}') : dezipped;
   _dealResponse(data);
  });
 } else {
  _dealResponse(result);
 }
});

Mark一下,也许你路过正好需要~~~

以上这篇Node层模拟实现multipart表单的文件上传示例就是小编分享给大家的全部内容了,希望能给大家一个参考,也希望大家多多支持三水点靠木。

Javascript 相关文章推荐
js实现图片漂浮效果的方法
Mar 02 Javascript
JavaScript实现单击下拉框选择直接跳转页面的方法
Jul 02 Javascript
JavaScript知识点整理
Dec 09 Javascript
详解javascript实现瀑布流绝对式布局
Jan 29 Javascript
基于JavaScript实现文字超出部分隐藏
Feb 29 Javascript
Angularjs之filter过滤器(推荐)
Nov 27 Javascript
ionic实现下拉刷新载入数据功能
May 11 Javascript
浅谈vuex 闲置状态重置方案
Jan 04 Javascript
Nuxt.js实战详解
Jan 18 Javascript
详解Vue用cmd创建项目
Feb 12 Javascript
微信小程序语音同步智能识别的实现案例代码解析
May 29 Javascript
LayUI+Shiro实现动态菜单并记住菜单收展的示例
May 06 Javascript
10行原生JS实现文字无缝滚动(超简单)
Jan 02 #Javascript
js原生实现移动端手指滑动轮播图效果的示例
Jan 02 #Javascript
vue父组件向子组件(props)传递数据的方法
Jan 02 #Javascript
基于wordpress的ajax写法详解
Jan 02 #Javascript
基于Vue的SPA动态修改页面title的方法(推荐)
Jan 02 #Javascript
jq.ajax+php+mysql实现关键字模糊查询(示例讲解)
Jan 02 #Javascript
使用async、enterproxy控制并发数量的方法详解
Jan 02 #Javascript
You might like
无线电波是什么?它是怎样传输的?
2021/03/01 无线电
PHP如何解决微信文章图片防盗链
2020/12/09 PHP
载入进度条 效果
2006/07/08 Javascript
北京奥运官方网站幻灯切换效果flash版打包下载
2008/01/30 Javascript
Extjs4 类的定义和扩展实例
2013/06/28 Javascript
JS将表单导出成EXCEL的实例代码
2013/11/11 Javascript
扩展jQuery对象时如何扩展成员变量具体怎么实现
2014/04/25 Javascript
js运动动画的八个知识点
2015/03/12 Javascript
基于BootStrap Metronic开发框架经验小结【五】Bootstrap File Input文件上传插件的用法详解
2016/05/12 Javascript
微信小程序  wx.request合法域名配置详解
2016/11/23 Javascript
JavaScript实现翻页功能(附效果图)
2017/02/16 Javascript
jQuery中复合选择器简单用法示例
2018/03/31 jQuery
JavaScript实现计算圆周率到小数点后100位的方法示例
2018/05/08 Javascript
React 使用Hooks简化受控组件的状态绑定
2019/03/18 Javascript
浅谈vue限制文本框输入数字的正确姿势
2019/09/02 Javascript
JS实现无限轮播无倒退效果
2020/09/21 Javascript
跟老齐学Python之不要红头文件(2)
2014/09/28 Python
Python3 能振兴 Python的原因分析
2014/11/28 Python
浅析Python多线程下的变量问题
2015/04/28 Python
利用Python脚本生成sitemap.xml的实现方法
2017/01/31 Python
Python 逐行分割大txt文件的方法
2017/10/10 Python
用pandas按列合并两个文件的实例
2018/04/12 Python
使用python存储网页上的图片实例
2018/05/22 Python
Python用61行代码实现图片像素化的示例代码
2018/12/10 Python
Python 调用PIL库失败的解决方法
2019/01/08 Python
Python连接Hadoop数据中遇到的各种坑(汇总)
2020/04/14 Python
关于Python不换行输出和不换行输出end=““不显示的问题(亲测已解决)
2020/10/27 Python
J2SDK1.5与J2SDK5.0有什么区别
2012/09/19 面试题
年终自我鉴定
2013/10/09 职场文书
八项规定整改方案
2014/02/21 职场文书
大学运动会入场词
2014/02/22 职场文书
药学职务聘任书
2014/03/29 职场文书
投标保密承诺书
2014/05/19 职场文书
论文诚信承诺书
2014/05/23 职场文书
大学优秀班集体申报材料
2014/05/23 职场文书
Python打包exe时各种异常处理方案总结
2021/05/18 Python