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 相关文章推荐
调试代码导致IE出错的避免方法
Apr 04 Javascript
jquery动态调整div大小使其宽度始终为浏览器宽度
Jun 06 Javascript
Jquery的基本对象转换和文档加载用法实例
Feb 25 Javascript
jQuery EasyUI Dialog拖不下来如何解决
Sep 28 Javascript
Bootstrap每天必学之表格
Nov 23 Javascript
Vue父组件调用子组件事件方法
Feb 23 Javascript
vue将对象新增的属性添加到检测序列的方法
Feb 24 Javascript
详解Angular路由之路由守卫
May 10 Javascript
详解在微信小程序的JS脚本中使用Promise来优化函数处理
Mar 06 Javascript
Echarts实现单条折线可拖拽效果
Dec 19 Javascript
Vue优化:常见会导致内存泄漏问题及优化详解
Aug 04 Javascript
微信小程序实现倒计时功能
Nov 19 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设计模式 DAO(数据访问对象模式)
2011/06/26 PHP
PHP字符过滤函数去除字符串最后一个逗号(rtrim)
2013/03/26 PHP
探讨PHP中OO之静态关键字以及类常量的详解
2013/06/07 PHP
php中的ini配置原理详解
2014/10/14 PHP
php使用sql server验证连接数据库的方法
2014/12/25 PHP
PHP 数组遍历foreach语法结构及实例
2016/06/13 PHP
JavaScript学习笔记(十七)js 优化
2010/02/04 Javascript
javascript下数值型比较难点说明
2010/06/07 Javascript
javascript完美拖拽的实现方法
2013/09/29 Javascript
jQuery多项选项卡的实现思路附样式及代码
2014/06/03 Javascript
理解jQuery stop()方法
2014/11/21 Javascript
基于bootstrap的文件上传控件bootstrap fileinput
2016/12/23 Javascript
javascript常用的设计模式
2017/02/09 Javascript
详解nodejs实现本地上传图片并预览功能(express4.0+)
2017/06/28 NodeJs
vue中for循环更改数据的实例代码(数据变化但页面数据未变)
2017/09/15 Javascript
深入理解Vue.js源码之事件机制
2017/09/27 Javascript
Angular自定义组件实现数据双向数据绑定的实例
2017/12/11 Javascript
JavaScript对象字面量和构造函数原理与用法详解
2020/04/18 Javascript
vue实现购物车的监听
2020/04/20 Javascript
python with提前退出遇到的坑与解决方案
2018/01/05 Python
python web自制框架之接受url传递过来的参数实例
2018/12/17 Python
pyshp创建shp点文件的方法
2018/12/31 Python
详解Python静态网页爬取获取高清壁纸
2019/04/23 Python
Python如何在DataFrame增加数值
2020/02/14 Python
css3实现平移效果(transfrom:translate)的示例
2020/11/13 HTML / CSS
物流专业大学的自我评价
2014/01/11 职场文书
党员教师一句话承诺
2014/05/30 职场文书
幼儿园爱国卫生月活动总结
2014/06/30 职场文书
党的群众路线整改落实情况汇报
2014/10/28 职场文书
计算机考试作弊检讨书1000字
2015/01/01 职场文书
交警失职检讨书
2015/01/26 职场文书
安全生产先进个人总结
2015/02/15 职场文书
教师节老师寄语
2015/05/28 职场文书
小学英语新课改心得体会
2016/01/22 职场文书
MySQL库表名大小写的选择
2021/06/05 MySQL
PO模式在selenium自动化测试框架的优势
2022/03/20 Python