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 25 Javascript
基于SVG的web页面图形绘制API介绍及编程演示
Jun 28 Javascript
node.js中的socket.io入门实例
Apr 26 Javascript
js图片预加载示例
Apr 30 Javascript
JavaScript代码生成PDF文件的方法
Feb 26 Javascript
JavaScript编写页面半透明遮罩效果的简单示例
May 09 Javascript
json对象转为字符串,当做参数传递时加密解密的实现方法
Jun 29 Javascript
浅谈js图片前端预览之filereader和window.URL.createObjectURL
Jun 30 Javascript
jQuery文本框得到与失去焦点动态改变样式效果
Sep 08 Javascript
jquery获取input输入框中的值
Nov 13 jQuery
JS Web Flex弹性盒子模型代码实例
Mar 10 Javascript
vue+elementUI(el-upload)图片压缩,默认同比例压缩操作
Aug 10 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
学习discuz php 引入文件的方法DISCUZ_ROOT
2009/06/21 PHP
php使用ob_start()实现图片存入变量的方法
2014/11/14 PHP
[原创]PHP实现字节数Byte转换为KB、MB、GB、TB的方法
2017/08/31 PHP
php 数据结构之链表队列
2017/10/17 PHP
thinkPHP5.1框架使用SemanticUI实现分页功能示例
2019/08/03 PHP
JavaScript 学习笔记(十四) 正则表达式
2010/01/22 Javascript
深入理解JavaScript系列(35):设计模式之迭代器模式详解
2015/03/03 Javascript
Javascript数据结构与算法之列表详解
2015/03/12 Javascript
jQuery实现从身份证号中获取出生日期和性别的方法分析
2016/02/25 Javascript
Vue.js第一天学习笔记(数据的双向绑定、常用指令)
2016/12/01 Javascript
javascript中json对象json数组json字符串互转及取值方法
2017/04/19 Javascript
JavaScript的六种继承方式(推荐)
2017/06/26 Javascript
vuex学习之Actions的用法详解
2017/08/29 Javascript
vue 兄弟组件的信息传递的方法实例详解
2019/08/30 Javascript
在Vue里如何把网页的数据导出到Excel的方法
2020/09/30 Javascript
使用js获取身份证年龄的示例代码
2020/12/11 Javascript
关于你不想知道的所有Python3 unicode特性
2014/11/28 Python
python实现的简单猜数字游戏
2015/04/04 Python
浅谈python中copy和deepcopy中的区别
2017/10/23 Python
Python利用turtle库绘制彩虹代码示例
2017/12/20 Python
利用python如何处理百万条数据(适用java新手)
2018/06/06 Python
Python登录系统界面实现详解
2019/06/25 Python
Python爬虫图片懒加载技术 selenium和PhantomJS解析
2019/09/18 Python
python读取ini配置文件过程示范
2019/12/23 Python
Python 3.10 的首个 PEP 诞生,内置类型 zip() 迎来新特性(推荐)
2020/07/03 Python
CSS3 animation实现逐帧动画效果
2016/06/02 HTML / CSS
物业总经理助理岗位职责
2014/06/29 职场文书
交通局领导班子群众路线教育实践活动对照检查材料思想汇报
2014/10/09 职场文书
2014年老干部工作总结
2014/11/21 职场文书
2014年村委会工作总结
2014/11/24 职场文书
2015年优质护理服务工作总结
2015/04/08 职场文书
乡镇团代会开幕词
2016/03/04 职场文书
个人道歉信大全
2019/04/11 职场文书
《学会生存》读后感3篇
2019/12/09 职场文书
Python绘制地图神器folium的新人入门指南
2021/05/23 Python
分析SQL窗口函数之取值窗口函数
2022/04/21 Oracle