jQuery+formdata实现上传进度特效遇到的问题


Posted in Javascript onFebruary 24, 2016

总结我做HTML5文件上传插件遇到的技术问题

先贴上源码:fileupload-html5.js(PS:公司使用seajs框架)

问题列表

1. JQUERY.AJAX没有监听上传进度的ONPROGRESS事件。

2. XMLHTTPREQUEST(XHR)跨域

问题解答

1. JQUERY没有给出ONPROGRESS事件的接口,必须从其他接口中找到原生XHR对象。

jQuery.ajax()返回的是jqXHR对象。jqXHR模仿XHR(原生),但没有模仿实现XHR的所有方法和属性(如:.upload),即使jqXHR增加了一个特有方法(如:.promise())。所以jqXHR并不是XHR的超集。

//下面是截取jQ内部的源码,$.ajax();返回的就是这个jqXHR(伪造XMLHttpRequest)
// Fake xhr
 jqXHR = {

  readyState: 0,

XHR的upload属性指向XMLHttpRequestUpload(IE10是XMLHttpRequestEventTarget),该对象的onprogress事件可以监听上传进度。既然jQ没有给出这个功能的api,但jQ某些数据上传方式是使用XHR的,所以我们可以从其它api中找到XHR。在XHR发送数据之前绑定onprogress事件可以实现上传进度功能。

我从OPTIONS参数配置中找到两个与XHR有关的属性:

- XHR:回调创建XMLHTTPREQUEST对象。

xhr()返回值是XHR,提供给jQ使用,即发送数据就是用这个XHR。我们可以通过xhr创建一个回调函数覆盖它,同样返回XHR,但在此绑定onprogress事件。

//jQ源码
// Get a new xhr
var handle, i,
 xhr = s.xhr();//[回调]在这里,下面是open方法

// Open the socket
// Passing null username, generates a login popup on Opera (#2865)
if ( s.username ) {
 xhr.open( s.type, s.url, s.async, s.username, s.password );
} else {
 xhr.open( s.type, s.url, s.async );
}

所以我们应该这样做:

$.ajax({
 //.....
 xhr: function() {
  var xhr = $.ajaxSettings.xhr();
  //绑定上传进度的回调函数
  xhr.upload.addEventListener('progress', progress, false);
  return xhr;//一定要返回,不然jQ没有XHR对象用了
 }
});

- XHRFIELDS:一对“文件名-文件值”组成的映射,用于设定原生的 XHR对象。

xhrFields属性指向jQ内部创建的XHR,我们可以根据xhrFields获得XMLHttpRequest。由于xhrFields的值只能是json对象,所以不能以下面方式获取。

//错误例子
$.ajax({
 //......
 xhrFields: {
  upload.onprogress: function() {
   //语法错误
  }
 }
});

我们可以借助XHR的onsendstart事件,如下:

$.ajax({
 //......
 xhrFields: {
  onsendstart: function() {
   //this是指向XHR
   this.upload.addEventListener('progress', progress, false);
  }
 }
});

2. XMLHTTPREQUESTⅡ(XHR)支持跨域,但需要后台允许。

//后台需发送头部验证
if($_REQUEST['cros']) {
 header("Access-Control-Allow-Origin:请求的域名");
}

根据后台给的接口,我需要增加一个参数cros。但我将这个参数与文件同事提交,却提示跨域限制。最后将这个参数放在url才行。

原来XHR跨域是有两次请求的,第一次是验证请求,浏览器根据请求目的地址自动发出options请求。若通过,才能发出自定义的post请求。所以将参数放在post请求里,第一次请求没有cros参数,即不能通过。

Javascript 相关文章推荐
JS 文件大小判断的实现代码
Apr 07 Javascript
zeroclipboard复制到剪切板的flash
Aug 04 Javascript
jquery的clone方法应用于textarea和select的bug修复
Jun 26 Javascript
使用Javascript简单实现图片无缝滚动
Dec 05 Javascript
javascript实现复选框全选或反选
Feb 04 Javascript
Angular.js实现多个checkbox只能选择一个的方法示例
Feb 24 Javascript
JS实现匀加速与匀减速运动的方法示例
Sep 04 Javascript
微信小程序返回多级页面的实现方法
Oct 27 Javascript
360提示[高危]使用存在漏洞的JQuery版本的解决方法
Oct 27 jQuery
基于JavaScript实现抽奖系统
Jan 16 Javascript
jQuery zTree搜索-关键字查询 递归无限层功能实现代码
Jan 25 jQuery
JavaScript Canvas实现验证码
Aug 02 Javascript
JQuery EasyUI的使用
Feb 24 #Javascript
使用jQuery监听DOM元素大小变化
Feb 24 #Javascript
JavaScript中的闭包
Feb 24 #Javascript
jQuery中判断对象是否存在的方法汇总
Feb 24 #Javascript
jquery中键盘事件小结
Feb 24 #Javascript
javascript实现九宫格相加数值相等
May 28 #Javascript
Javascript类型转换的规则实例解析
Feb 23 #Javascript
You might like
一个简单的自动发送邮件系统(三)
2006/10/09 PHP
PHP之认识(二)关于Traits的用法详解
2019/04/11 PHP
PHP常量define和const的区别详解
2019/05/18 PHP
php7 新增功能实例总结
2020/05/25 PHP
Javascript实例教程(19) 使用HoTMetal(5)
2006/12/23 Javascript
jquery 插件实现图片延迟加载效果代码
2010/02/06 Javascript
Javascript查询DBpedia小应用实例学习
2013/03/07 Javascript
JavaScript获取和设置CheckBox状态的简单方法
2013/07/05 Javascript
NodeJS制作爬虫全过程
2014/12/22 NodeJs
jquery模拟实现鼠标指针停止运动事件
2016/01/12 Javascript
jQuery Tags Input Plugin(添加/删除标签插件)详解
2016/06/20 Javascript
原生js开发的日历插件
2017/02/04 Javascript
Node调用Java的示例代码
2017/09/20 Javascript
jQuery实现弹窗下底部页面禁止滑动效果
2017/12/19 jQuery
详解基于electron制作一个node压缩图片的桌面应用
2019/01/29 Javascript
[01:28:31]《加油DOTA》真人秀 第五期
2014/09/01 DOTA
将Emacs打造成强大的Python代码编辑工具
2015/11/20 Python
Python简单格式化时间的方法【strftime函数】
2016/09/18 Python
Centos下实现安装Python3.6和Python2共存
2018/08/15 Python
python中join()方法介绍
2018/10/11 Python
Python数据可视化教程之Matplotlib实现各种图表实例
2019/01/13 Python
python实现读取excel文件中所有sheet操作示例
2019/08/09 Python
python实现数字炸弹游戏
2020/07/17 Python
教你如何用python操作摄像头以及对视频流的处理
2020/10/12 Python
详解Anaconda安装tensorflow报错问题解决方法
2020/11/01 Python
美国女孩服装购物网站:Justice
2017/03/04 全球购物
英国健身超市:Fitness Superstore
2019/06/17 全球购物
《梅花魂》教学反思
2014/04/30 职场文书
开展党的群众路线教育实践活动剖析材料
2014/10/13 职场文书
2014年审计人员工作总结
2014/12/19 职场文书
拿破仑传读书笔记
2015/07/01 职场文书
2016年度继续教育学习心得体会
2016/01/19 职场文书
vue实现简单数据双向绑定
2021/04/28 Vue.js
vue基于Teleport实现Modal组件
2021/05/31 Vue.js
css中有哪些方式可以隐藏页面元素及区别
2022/06/16 HTML / CSS
java.util.NoSuchElementException原因及两种解决方法
2022/06/28 Java/Android