视频1 视频21 视频41 视频61 视频文章1 视频文章21 视频文章41 视频文章61 推荐1 推荐3 推荐5 推荐7 推荐9 推荐11 推荐13 推荐15 推荐17 推荐19 推荐21 推荐23 推荐25 推荐27 推荐29 推荐31 推荐33 推荐35 推荐37 推荐39 推荐41 推荐43 推荐45 推荐47 推荐49 关键词1 关键词101 关键词201 关键词301 关键词401 关键词501 关键词601 关键词701 关键词801 关键词901 关键词1001 关键词1101 关键词1201 关键词1301 关键词1401 关键词1501 关键词1601 关键词1701 关键词1801 关键词1901 视频扩展1 视频扩展6 视频扩展11 视频扩展16 文章1 文章201 文章401 文章601 文章801 文章1001 资讯1 资讯501 资讯1001 资讯1501 标签1 标签501 标签1001 关键词1 关键词501 关键词1001 关键词1501 专题2001
HTML5文件上传插件遇到的技术问题
2020-11-27 15:08:12 责编:小采
文档


总结我做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 xhrvar 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参数,即不能通过。

下载本文
显示全文
专题