Node.js实现兼容IE789的文件上传进度条


Posted in Javascript onSeptember 02, 2016

Nodejs对文件上传的处理

在Express4里req.files已经是undefined了;现在用的最多的可能就是formidable了,你知道了它有个progress事件,于是心中大喜,低版本IE的进度条有戏了;OK,试一下:

form 
 .on('error',function(err){ 
  console.log(err);
 }) 
 .on('aborted',function(){ 
  console.log('aborted'); 
 })
 .on('progress',function(bytesReceived, bytesExpected){ 
  var n=parseInt(parseFloat(bytesReceived/bytesExpected).toFixed(2)*100); 
  console.log(n); 
 });

是的,你很高兴的看到了,控制台按照预期打印了一串进度值;那么,再进一步;

form 
 .on('progress',function(bytesReceived, bytesExpected){ 
  var n=parseInt(parseFloat(bytesReceived/bytesExpected).toFixed(2)*100); 
  res.write('<script>window.parent.call('+n+')</script>'); 
  //无刷新上传,你们懂的 console.log(n); 
 });

call方法即在页面上显示进度值;很不幸,你只能看到最后的100%,看不到上传具体详细的进度值;再探...

接下来换个思路,试一下,将进度值保存到session里,额外加一个请求来轮询这个进度值,哎哟,不错哦!为了保证你请求的进度值是你这次上传的进度值而不是其他上传的进度值,需要在上传的请求里和额外的请求里约定一个token值;现在又来一个问题就是怎么在请求的时候得到这个token,由于文件上传的请求体在Request Payload里,所以req.body拿不到带过去的值,我也不想去解析这堆了,当然我也解析不了;放在url里最好,问题在于有时候得刷新两次来刷新token,不好!不得已,我还是放在cookie里吧!

var cookies=function () { 
  var cks=req.headers.cookie.split(';'),obj={}; 
  for(var i=0;i<cks.length;i++){ 
   obj[cks[i].split('=')[0].replace(/\s+/ig,'')]=unescape(cks[i].split('=')[1]); 
  } 
  return obj; 
 }(); 
 var queryToken=cookies.__token__;
 
 form .on('progress',function(bytesReceived, bytesExpected){ 
  var n=parseInt(parseFloat(form.bytesReceived/form.bytesExpected).toFixed(2)*100); 
  if (req.session['file'+queryToken]) {  
   req.session['file'+queryToken].percent=n; 
  }else{ 
   req.session['file'+queryToken]={ 
    token:queryToken, 
    percent:n 
   } 
  }; 
  console.log(n); 
 });

为了IE789,我来轮询进度值了,原谅我,其实我的心很痛;

var getData=function(){ 
  $.post('/uploader',{ 
   getfileinfo:1, 
   uploadtoken:utils.cookie.getCookie('__token__') 
  })
  .then(function(data){ 
   console.log(data);
   if (data.mes<0) { 
    getData(); 
   }else{ 
    var pros=data.info; 
    call(pros.percent);
    if (pros.percent!='100') { 
     getData(); 
    }; 
   }; 
  }); 
 } 
 getData();

call方法即在页面上显示进度值;很不幸,你只能看到最后的100%,看不到上传具体详细的进度值;再探...

好吧,我又一次沦陷了;不过还是感觉不对劲,ajax轮询没有问题,问题在于session里要等到上传完毕才有值,所以只能看到100%,看不到详细进度值;我是否可以认为,在progress里,之前的res.write和这次的req.session被挂起了呢,但是它又保存了每次的执行结果,直到progress完再释放,所以只能看到100%;没心情看formidable的源码,当然我也看不咋懂,我就先这么认为吧!

既然ajax轮询没问题,那么就是保存到session不得劲了;实在不成,放到global里试试吧,总不会往全局对象里塞个值也会挂起吧;稍作改动放到global里:

form 
 .on('progress',function(bytesReceived, bytesExpected){ 
  var n=parseInt(parseFloat(form.bytesReceived/form.bytesExpected).toFixed(2)*100);
  if (global['file'+queryToken]) { 
   global['file'+queryToken].percent=n; 
  }else{ 
   global['file'+queryToken]={ 
    token:queryToken, 
    percent:n 
   } 
  }; 
  console.log(n); 
 });

继续轮询。

漂亮,完全就是那么回事!在chrome里看到的和HTML5的进度一个效果,只是在IE789里会有点卡顿的感觉,不过还是能看到详细的进度值的;毕竟老浏览器身子骨不咋地,你们懂的;还有,每次上传都往global里塞值,怎么也得适当的清理一下吧,文件上传完毕,转移到指定目录后global['file'+queryToken]=null

然而,轮询,就是一个接一个好多好多的请求,这里也许会出问题;要不限制一下吧,间隔500ms请求一次进度值;恩,IE789进度条就这么解决了,说好的丢掉flash;虽然这个轮询可以兼容所有浏览器,但毕竟要浪费那么多请求,还是判断下,在IE789以外继续HTML5吧!

其实衡量一下,额外加个flash上传和额外的请求,哪个更值呢,原谅我不懂flash,就不多说了,反正我很不喜欢在页面上加一下额外的文件;

总结

关于文件上传的组件,还有很多的细节处理,本想弄一个JS文件的,后来一想,为了可复用性更强,还是作为一个独立的页面搞比较好,需要上传的地方,iframe一下就行了,肯定比弄一个JS文件要好很多。以上就是这篇文章的全部内容,希望能够对大家的学习或者工作带来一定的帮助,如果有疑问大家可以留言交流。

Javascript 相关文章推荐
用JavaScript显示随机图像或引用
Apr 21 Javascript
Js制作简单弹出层DIV在页面居中 中间显示遮罩的具体方法
Aug 08 Javascript
jQuery Validate 验证,校验规则写在控件中的具体实例
Feb 27 Javascript
jQuery中:first选择器用法实例
Dec 30 Javascript
最常见的左侧分类菜单栏jQuery实现代码
Nov 28 Javascript
Zepto实现密码的隐藏/显示
Apr 07 Javascript
深入理解vue-router之keep-alive
Aug 31 Javascript
js将当前时间格式化为 年-月-日 时:分:秒的实现代码
Jan 20 Javascript
vue点击input弹出带搜索键盘并监听该元素的方法
Aug 25 Javascript
js限制输入框只能输入数字(onkeyup触发)
Sep 28 Javascript
微信小程序实现滚动加载更多的代码
Dec 06 Javascript
vue 里面的 $forceUpdate() 强制实例重新渲染操作
Sep 21 Javascript
AngularJs  Understanding Angular Templates
Sep 02 #Javascript
jquery 中toggle的2种用法详解(推荐)
Sep 02 #Javascript
浅谈JS中的三种字符串连接方式及其性能比较
Sep 02 #Javascript
AngularJs  E2E Testing 详解
Sep 02 #Javascript
解决node.js安装包失败的几种方法
Sep 02 #Javascript
js两种拼接字符串的简单方法(必看)
Sep 02 #Javascript
AngularJs Understanding the Controller Component
Sep 02 #Javascript
You might like
php实现统计网站在线人数的方法
2015/05/12 PHP
php实现统计二进制中1的个数算法示例
2018/01/23 PHP
laravel中Redis队列监听中断的分析
2020/09/14 PHP
Extjs3.0 checkboxGroup 动态添加item实现思路
2013/08/14 Javascript
js算法中的排序、数组去重详细概述
2013/10/14 Javascript
js获取IFRAME当前的URL的方法
2013/11/13 Javascript
js处理php输出时间戳对不上号的解决方法
2014/06/20 Javascript
jQuery+html5+css3实现圆角无刷新表单带输入验证功能代码
2015/08/21 Javascript
jQuery包裹节点用法完整示例
2016/09/13 Javascript
H5用户注册表单页 注册模态框!
2016/09/17 Javascript
vue-dialog的弹出层组件
2020/05/25 Javascript
vue.js如何更改默认端口号8080为指定端口的方法
2017/07/14 Javascript
jQuery Datatables表头不对齐的解决办法
2017/11/27 jQuery
Cocos2d实现刮刮卡效果
2018/12/20 Javascript
Node.js动手撸一个静态资源服务器的方法
2019/03/09 Javascript
jquery弹窗时禁止body滚动条滚动的例子
2019/09/21 jQuery
深入分析JavaScript 事件循环(Event Loop)
2020/06/19 Javascript
python获取外网ip地址的方法总结
2015/07/02 Python
利用python打开摄像头及颜色检测方法
2018/08/03 Python
python pyheatmap包绘制热力图
2018/11/09 Python
Django2.1.3 中间件使用详解
2018/11/26 Python
使用Python 正则匹配两个特定字符之间的字符方法
2018/12/24 Python
pandas DataFrame 警告(SettingWithCopyWarning)的解决
2019/07/23 Python
pygame编写音乐播放器的实现代码示例
2019/11/19 Python
python 中不同包 类 方法 之间的调用详解
2020/03/09 Python
Python request使用方法及问题总结
2020/04/26 Python
python安装和pycharm环境搭建设置方法
2020/05/27 Python
CSS3之多背景background使用示例
2013/10/18 HTML / CSS
美国高档帽子网上商店:Hats.com
2018/08/09 全球购物
南京市纪委监察局整改方案
2014/09/16 职场文书
中层领导干部群众路线对照检查材料思想汇报
2014/10/02 职场文书
2014年司法局工作总结
2014/12/11 职场文书
民间借贷借条范本
2015/05/25 职场文书
出生证明范本
2015/06/15 职场文书
创业项目(超低成本创业项目)
2019/08/16 职场文书
详解Flutter网络请求Dio库的使用及封装
2022/04/14 Java/Android