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 相关文章推荐
JavaScript 常用函数库详解
Oct 21 Javascript
超级24小时弹窗代码 24小时退出弹窗代码 100%弹窗代码(IE only)
Jun 11 Javascript
JavaScript动态插入script的基本思路及实现函数
Nov 11 Javascript
动态加载jquery库的方法
Feb 12 Javascript
ActiveX控件与Javascript之间的交互示例
Jun 04 Javascript
javascript实现的右下角弹窗实例
Apr 24 Javascript
浅谈javascript语法和定时函数
May 03 Javascript
AngularJs Understanding the Model Component
Sep 02 Javascript
js实现五星评价功能
Mar 08 Javascript
微信小程序中实现手指缩放图片的示例代码
Mar 13 Javascript
基于vue实现一个禅道主页拖拽效果
May 27 Javascript
在vue中使用回调函数,this调用无效的解决
Aug 11 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
用PHP实现文件上传二法
2006/10/09 PHP
在同一窗体中使用PHP来处理多个提交任务
2008/05/08 PHP
php面向对象 字段的声明与使用
2012/06/14 PHP
php可应用于面包屑导航的递归寻找家谱树实现方法
2015/02/02 PHP
php实现图片以base64显示的方法
2016/10/13 PHP
Yii2设置默认控制器的两种方法
2017/05/19 PHP
PHP实现爬虫爬取图片代码实例
2021/03/03 PHP
jquery选择器需要注意的问题
2014/11/26 Javascript
jQuery实现的进度条效果
2015/07/15 Javascript
JavaScript函数学习总结以及相关的编程习惯指南
2015/11/16 Javascript
基于JavaScript实现TAB标签效果
2016/01/12 Javascript
javascript表单处理具体实现代码(表单、链接、按钮)
2016/05/07 Javascript
原生JS实现简单放大镜效果
2017/02/08 Javascript
图解Javascript——作用域、作用域链、闭包
2017/03/21 Javascript
微信小程序调用PHP后台接口 解析纯html文本
2017/06/13 Javascript
详解node.js中的npm和webpack配置方法
2018/01/21 Javascript
浅谈webpack 四个核心概念之Entry
2019/06/12 Javascript
JS window对象简单操作完整示例
2020/01/14 Javascript
[01:29]Ti4循环赛第三日精彩回顾
2014/07/13 DOTA
浅谈Python实现贪心算法与活动安排问题
2017/12/19 Python
pygame游戏之旅 添加键盘按键的方法
2018/11/20 Python
详解Python中的分支和循环结构
2020/02/11 Python
Python Selenium实现无可视化界面过程解析
2020/08/25 Python
Python try except finally资源回收的实现
2021/01/25 Python
详解canvas.toDataURL()报错的解决方案全都在这了
2020/03/31 HTML / CSS
全球速卖通西班牙站:AliExpress西班牙
2017/10/30 全球购物
泰国第一的化妆品网站:Konvy
2018/02/25 全球购物
物业管理应届生求职信
2013/10/28 职场文书
幼儿如何来做好自我评价
2013/11/05 职场文书
竞选班委演讲稿
2014/04/28 职场文书
充分就业社区汇报材料
2014/05/07 职场文书
幼儿园秋季开学寄语
2014/08/02 职场文书
单位委托书范本(3篇)
2014/09/18 职场文书
用Python将GIF动图分解成多张静态图片
2021/06/11 Python
Java方法重载和方法重写的区别到底在哪?
2021/06/11 Java/Android
Spring中bean的生命周期之getSingleton方法
2021/06/30 Java/Android