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 相关文章推荐
基于jquery跨浏览器显示的file上传控件
Oct 24 Javascript
JSON 数字排序多字段排序介绍
Sep 18 Javascript
addEventListener()第三个参数useCapture (Boolean)详细解析
Nov 07 Javascript
nw.js实现类似微信的聊天软件
Mar 16 Javascript
基于JavaScript实现Json数据根据某个字段进行排序
Nov 24 Javascript
微信小程序签到功能
Oct 31 Javascript
JavaScript仿京东秒杀倒计时
Mar 17 Javascript
es6函数之尾调用优化实例分析
Apr 25 Javascript
jQuery实现的上拉刷新功能组件示例
May 01 jQuery
浅析我对JS延迟异步脚本的思考
Oct 12 Javascript
JavaScript小技巧带你提升你的代码技能
Sep 15 Javascript
JavaScript ES6的函数拓展
Jan 18 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 执行系统命令的方法
2009/07/07 PHP
关于页面优化和伪静态
2009/10/11 PHP
一篇有意思的技术文章php介绍篇
2010/10/26 PHP
php数组的一些常见操作汇总
2011/07/17 PHP
php array的学习笔记
2012/05/10 PHP
PHP生成唯一的促销/优惠/折扣码(附源码)
2012/12/28 PHP
基于Zookeeper的使用详解
2013/05/02 PHP
PHP的反射类ReflectionClass、ReflectionMethod使用实例
2014/08/05 PHP
php防止恶意刷新与刷票的方法
2014/11/21 PHP
php计算数组相同值出现次数的代码(array_count_values)
2015/01/20 PHP
php实现用于删除整个目录的递归函数
2015/03/16 PHP
PHP使用缓存即时输出内容(output buffering)的方法
2015/08/03 PHP
利用PHP生成CSV文件简单示例
2016/12/21 PHP
几行代码轻松搞定jquery实现flash8类似的连接效果
2007/05/03 Javascript
基于jquery的checkbox下拉框插件代码
2010/06/25 Javascript
Node.js生成HttpStatusCode辅助类发布到npm
2013/04/09 Javascript
Js操作Select大全(取值、设置选中等等)
2013/10/29 Javascript
在JavaScript应用中使用RequireJS来实现延迟加载
2015/07/01 Javascript
基于JS实现仿京东搜索栏随滑动透明度渐变效果
2017/07/10 Javascript
Vue v2.4中新增的$attrs及$listeners属性使用教程
2018/01/08 Javascript
JS实现快递单打印功能【推荐】
2018/06/21 Javascript
Python模拟百度登录实例详解
2016/01/20 Python
python安装与使用redis的方法
2016/04/19 Python
Python实现二维有序数组查找的方法
2016/04/27 Python
python中字符串类型json操作的注意事项
2017/05/02 Python
python 设置文件编码格式的实现方法
2017/12/21 Python
Pandas Shift函数的基础入门学习笔记
2018/11/16 Python
python super的使用方法及实例详解
2019/09/25 Python
CSS3实现伪类hover离开时平滑过渡效果示例
2017/08/10 HTML / CSS
"火柴棍式"程序员面试题
2014/03/16 面试题
一道SQL面试题
2012/12/31 面试题
爱国主义演讲稿
2014/05/07 职场文书
就业意向协议书
2015/01/29 职场文书
运动会加油稿
2015/07/22 职场文书
Django中session进行权限管理的使用
2021/07/09 Python
MySql统计函数COUNT的具体使用详解
2022/08/14 MySQL