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 相关文章推荐
JSQL SQLProxy 的 php 版本代码
May 05 Javascript
一个关于javascript匿名函数的问题分析
Mar 30 Javascript
每天一篇javascript学习小结(属性定义方法)
Nov 19 Javascript
JS获取月份最后天数、最大天数与某日周数的方法
Dec 08 Javascript
最全面的JS倒计时代码
Sep 17 Javascript
AngularJS出现$http异步后台无法获取请求参数问题的解决方法
Nov 03 Javascript
AngularJS中update两次出现$promise属性无法识别的解决方法
Jan 05 Javascript
微信小程序 Tab页切换更新数据
Jan 05 Javascript
MUI实现上拉加载和下拉刷新效果
Jun 30 Javascript
vue实现文章内容过长点击阅读全文功能的实例
Dec 28 Javascript
生产制造追溯系统之在线打印功能
Jun 03 Javascript
微信小程序背景音乐开发详解
Dec 12 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
德生PL990的分析评价
2021/03/02 无线电
WINDOWS服务器安装多套PHP的另类解决方案
2006/10/09 PHP
php email邮箱正则
2008/10/08 PHP
php中使用sftp教程
2015/03/30 PHP
PHP中的traits简单使用实例
2015/05/13 PHP
Laravel接收前端ajax传来的数据的实例代码
2017/07/20 PHP
显示今天的日期js代码(阳历和农历)
2014/09/30 Javascript
JavaScript通过prototype给对象定义属性用法实例
2015/03/23 Javascript
jQuery使用hide方法隐藏指定元素class样式用法实例
2015/03/30 Javascript
Javascript中prototype的使用详解
2016/06/18 Javascript
Bootstrap学习笔记之进度条、媒体对象实例详解
2017/03/09 Javascript
JS实现的Unicode编码转换操作示例
2017/04/28 Javascript
详解在Vue中如何使用axios跨域访问数据
2017/07/07 Javascript
解决vue.js在编写过程中出现空格不规范报错的问题
2017/09/20 Javascript
使用JS中的Replace()方法遇到的问题小结
2017/10/20 Javascript
详解vue通过NGINX部署在子目录或者二级目录实践
2018/09/03 Javascript
JavaScript中0、空字符串、'0'是true还是false的知识点分享
2019/09/16 Javascript
详解Vue3 Composition API中的提取和重用逻辑
2020/04/29 Javascript
javascript实现点击按钮切换轮播图功能
2020/09/23 Javascript
详解JavaScript 中的批处理和缓存
2020/11/19 Javascript
解决vue项目本地启动时无法携带cookie的问题
2021/02/06 Vue.js
python返回昨天日期的方法
2015/05/13 Python
python开发之tkinter实现图形随鼠标移动的方法
2015/11/11 Python
Python中py文件引用另一个py文件变量的方法
2018/04/29 Python
python3 selenium 切换窗口的几种方法小结
2018/05/21 Python
python中dict字典的查询键值对 遍历 排序 创建 访问 更新 删除基础操作方法
2018/09/13 Python
python Matplotlib数据可视化(2):详解三大容器对象与常用设置
2020/09/30 Python
python实现企业微信定时发送文本消息的实例代码
2020/11/25 Python
Jupyter安装拓展nbextensions及解决官网下载慢的问题
2021/03/03 Python
DJI大疆德国官方商城:大疆无人机
2018/09/01 全球购物
Desigual美国官方网站:西班牙服装品牌
2019/03/29 全球购物
财务管理职业生涯规划范文
2013/12/27 职场文书
幼儿园中秋节活动方案2013
2014/01/29 职场文书
九年级政治教学反思
2014/02/06 职场文书
教导主任竞聘演讲稿
2014/05/16 职场文书
论文答辩开场白大全
2015/05/27 职场文书