XMLHttpRequest2的进步之处
本文参考自:XMLHttpRequest2 新技巧 (重点保留demo,方便自己日后查阅)
HTML5是现在web开发中的热点,虽然关于web app和local app一直有争论,但是从技术学习的角度,html5技术无疑是值得学习的。最近看了看XHR2,大概了解了其中比之前进步的要点,记录下来以备日后复习:
首先,XHR2的官方注解可见:http://dvcs.w3.org/hg/xhr/raw-file/tip/Overview.html
XHR2主要的新功能有(我平时开发遇到的):
上传下载二进制数据
上传进度事件的支持
跨域请求
同时结合html5中的File API,我们就可以在网页中实现更丰富的功能。
一) 二进制数据处理
以前通过 XHR 抓取二进制 blob 形式的文件是很痛苦的事情。从技术上来说,这甚至是不可能的实现。有一种广为流传的一种技巧,是将 MIME 类型替换为由用户定义的字符集,如下所示:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
|
var xhr = new XMLHttpRequest(); xhr.open( 'GET' , '/path/to/image.png' , true ); xhr.overrideMimeType( 'text/plain; charset=x-user-defined' ); xhr.onreadystatechange = function (e) { if ( this .readyState == 4 && this .status == 200) { var binStr = this .responseText; for ( var i = 0, len = binStr.length; i < len; ++i) { var c = binStr.charCodeAt(i); //String.fromCharCode(c & 0xff); var byte = c & 0xff; } } }; xhr.send(); |
虽然这种方法可行,但是 responseText 中实际返回的并不是二进制 blob,而是代表图片文件的二进制字符串。我们要巧妙地让服务器在不作处理的情况下,将这些数据传递回去。
现在XHR2中,新增了responseType和response属性,可以告知浏览器我们希望返回什么格式的数据。
xhr.responseType
在发送请求前,根据您的数据需要,将 xhr.responseType 设置为“text”、“arraybuffer”、“blob”或“document”。请注意,设置(或忽略)xhr.responseType = '' 会默认将响应设为“text”。xhr.response
成功发送请求后,xhr 的响应属性会包含 DOMString、ArrayBuffer、Blob 或 Document 形式(具体取决于 responseTyp 的设置)的请求数据。
凭借这个优秀的新属性,我们可以修改上一个示例:以 ArrayBuffer 而非字符串的形式抓取图片。将缓冲区移交给 BlobBuilder API 可创建 Blob:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
|
BlobBuilder = window.MozBlobBuilder || window.WebKitBlobBuilder || window.BlobBuilder; var xhr = new XMLHttpRequest(); xhr.open( 'GET' , '/path/to/image.png' , true ); xhr.responseType = 'arraybuffer' ; xhr.onload = function (e) { if ( this .status == 200) { var bb = new BlobBuilder(); bb.append( this .response); // Note: not xhr.responseText var blob = bb.getBlob( 'image/png' ); ... } }; xhr.send(); |
此外ArrayBuffer是二进制数据通用的固定长度容器。如果您需要原始数据的通用缓冲区,ArrayBuffer 就非常好用,但是它真正强大的功能是让您使用 JavaScript 类型数组创建底层数据的“视图”。实际上,可以通过单个 ArrayBuffer 来源创建多个视图。例如,您可以创建一个 8 位整数数组,与来自相同数据的现有 32 位整数数组共享同一个 ArrayBuffer。底层数据保持不变,我们只是创建其不同的表示方法。
1
2
3
4
5
6
7
8
9
10
11
|
var xhr = new XMLHttpRequest(); xhr.open( 'GET' , '/path/to/image.png' , true ); xhr.responseType = 'arraybuffer' ; xhr.onload = function (e) { var uInt8Array = new Uint8Array( this .response); // this.response == uInt8Array.buffer // var byte3 = uInt8Array[4]; // byte at offset 4 ... }; xhr.send(); |
如果您要直接处理 Blob 且/或不需要操作任何文件的字节,可使用xhr.responseType='blob'
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
|
window.URL = window.URL || window.webkitURL; // Take care of vendor prefixes. var xhr = new XMLHttpRequest(); xhr.open( 'GET' , '/path/to/image.png' , true ); xhr.responseType = 'blob' ; xhr.onload = function (e) { if ( this .status == 200) { var blob = this .response; var img = document.createElement( 'img' ); img.onload = function (e) { window.URL.revokeObjectURL(img.src); // Clean up after yourself. }; img.src = window.URL.createObjectURL(blob); document.body.appendChild(img); ... } }; xhr.send(); |
Blob 可用于很多场合,包括保存到 indexedDB、写入 HTML5 文件系统 或创建 Blob 网址(如本例中所示)。
二)发送数据
能够下载各种格式的数据固然是件好事,但是如果不能将这些丰富格式的数据送回本垒(服务器),那就毫无意义了。XMLHttpRequest 有时候会限制我们发送 DOMString 或 Document (XML) 数据。但是现在不会了。现已替换成经过修改的 send() 方法,可接受以下任何类型:DOMString、Document、FormData、Blob、File、ArrayBuffer。本部分的其余内容中的示例演示了如何使用各类型发送数据。
1)发送字符串数据:xhr.send(DOMString)
1
2
3
4
5
6
7
8
9
10
11
12
13
|
function sendText(txt) { var xhr = new XMLHttpRequest(); xhr.open( 'POST' , '/server' , true ); xhr.responseType = 'text' ; xhr.onload = function (e) { if ( this .status == 200) { console.log( this .responseText); } }; xhr.send(txt); } sendText( 'test string' ); |
2)提交表单:xhr.send(FormData)
1
2
3
4
5
6
7
8
9
10
11
|
function sendForm() { var formData = new FormData(); formData.append( 'username' , 'johndoe' ); formData.append( 'id' , 123456); var xhr = new XMLHttpRequest(); xhr.open( 'POST' , '/server' , true ); xhr.onload = function (e) { ... }; xhr.send(formData); } |
由form数据初始化formData
1
2
3
4
5
|
< form id = "myform" name = "myform" action = "/server" > < input type = "text" name = "username" value = "johndoe" > < input type = "number" name = "id" value = "123456" > < input type = "submit" onclick = "return sendForm(this.form);" > </ form > |
1
2
3
4
5
6
7
8
9
10
11
12
13
|
function sendForm(form) { var formData = new FormData(form); formData.append( 'secret_token' , '1234567890' ); // Append extra data before send. var xhr = new XMLHttpRequest(); xhr.open( 'POST' , form.action, true ); xhr.onload = function (e) { ... }; xhr.send(formData); return false ; // Prevent page from submitting. } |
同时可以包含文件上传
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
|
function uploadFiles(url, files) { var formData = new FormData(); for ( var i = 0, file; file = files[i]; ++i) { formData.append(file.name, file); } var xhr = new XMLHttpRequest(); xhr.open( 'POST' , url, true ); xhr.onload = function (e) { ... }; xhr.send(formData); // multipart/form-data } document.querySelector( 'input[type="file"]' ).addEventListener( 'change' , function (e) { uploadFiles( '/server' , this .files); }, false ); |
3)上传文件或 blob:xhr.send(Blob),同时demo下上传事件如果使用
1
|
< progress min = "0" max = "100" value = "0" >0% complete</ progress > |
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
|
function upload(blobOrFile) { var xhr = new XMLHttpRequest(); xhr.open( 'POST' , '/server' , true ); xhr.onload = function (e) { ... }; // Listen to the upload progress. var progressBar = document.querySelector( 'progress' ); xhr.upload.onprogress = function (e) { if (e.lengthComputable) { progressBar.value = (e.loaded / e.total) * 100; progressBar.textContent = progressBar.value; // Fallback for unsupported browsers. } }; xhr.send(blobOrFile); } // Take care of vendor prefixes. BlobBuilder = window.MozBlobBuilder || window.WebKitBlobBuilder || window.BlobBuilder; var bb = new BlobBuilder(); bb.append( 'hello world' ); upload(bb.getBlob( 'text/plain' )); |
4)上传字节:xhr.send(ArrayBuffer)
1
2
3
4
5
6
7
8
9
|
function sendArrayBuffer() { var xhr = new XMLHttpRequest(); xhr.open( 'POST' , '/server' , true ); xhr.onload = function (e) { ... }; var uInt8Array = new Uint8Array([1, 2, 3]); xhr.send(uInt8Array.buffer); } |
三)跨源请求 (CORS)
CORS 允许一个域上的网络应用向另一个域提交跨域 AJAX 请求。启用此功能非常简单,只需由服务器发送一个响应标头即可。
允许来自 example.com 的请求:
1
|
Access-Control-Allow-Origin: http://example.com |
要允许任何域向您提交请求:
1
|
Access-Control-Allow-Origin: * |
提交跨域请求时和以前没有区别。
1
2
3
4
5
6
7
|
var xhr = new XMLHttpRequest(); xhr.onload = function (e) { var data = JSON.parse( this .response); ... } xhr.send(); |
四)有用的实例
1)下载文件并保存到文件系统
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
|
window.requestFileSystem = window.requestFileSystem || window.webkitRequestFileSystem; function onError(e) { console.log( 'Error' , e); } var xhr = new XMLHttpRequest(); xhr.open( 'GET' , '/path/to/image.png' , true ); xhr.responseType = 'arraybuffer' ; xhr.onload = function (e) { window.requestFileSystem(TEMPORARY, 1024 * 1024, function (fs) { fs.root.getFile( 'image.png' , {create: true }, function (fileEntry) { fileEntry.createWriter( function (writer) { writer.onwrite = function (e) { ... }; writer.onerror = function (e) { ... }; var bb = new BlobBuilder(); bb.append(xhr.response); writer.write(bb.getBlob( 'image/png' )); }, onError); }, onError); }, onError); }; xhr.send(); |
2)分割文件并上传各个部分
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
|
window.BlobBuilder = window.MozBlobBuilder || window.WebKitBlobBuilder || window.BlobBuilder; function upload(blobOrFile) { var xhr = new XMLHttpRequest(); xhr.open( 'POST' , '/server' , true ); xhr.onload = function (e) { ... }; xhr.send(blobOrFile); } document.querySelector( 'input[type="file"]' ).addEventListener( 'change' , function (e) { var blob = this .files[0]; const BYTES_PER_CHUNK = 1024 * 1024; // 1MB chunk sizes. const SIZE = blob.size; var start = 0; var end = BYTES_PER_CHUNK; while (start < SIZE) { // Note: blob.slice has changed semantics and been prefixed. Seehttp://goo.gl/U9mE5. if ( 'mozSlice' in blob) { var chunk = blob.mozSlice(start, end); } else { var chunk = blob.webkitSlice(start, end); } upload(chunk); start = end; end = start + BYTES_PER_CHUNK; } }, false ); })();
|
http://mozilla.com.cn/post/34886/
XMLHttpRequest2的进步之处的更多相关文章
- 【JavsScript】XMLHttpRequest2的进步之处
本文参考自:XMLHttpRequest2 新技巧 (重点保留demo,方便自己日后查阅) HTML5是现在web开发中的热点,虽然关于web app和local app一直有争论,但是从技术学习的角 ...
- Nginx CORS实现JS跨域
1. 什么是跨域 简单地理解就是因为JavaScript同源策略的限制,a.com 域名下的js无法操作b.com或是c.a.com域名下的对象. 同源是指相同的协议.域名.端口.特别注意两点: 如果 ...
- JSONP、图片Ping、XMLHttpRequest2.0等跨域资源请求(CORS)
跨域:当协议.主域名.子域名.端口号中任意一个不相同时都不算同一个域,而在不同域之间请求数据即为跨域请求.解决方法有以下几种(如有错误欢迎指出)以请求图片url为例: 1.通过XMLHttpReque ...
- CSS预处器的对比——Sass、Less和Stylus
预处器的对比--Sass.LESS和Stylus 转载: 英文原文:http://net.tutsplus.com/tutorials/html-css-techniques/sass-vs-less ...
- 数据库(SQL Server)管理数据库表~新奇之处
说到“数据库”,我总有一种莫名的感觉,在刚刚接触到的数据库中就让我似懂非懂渡过着,于是思考着.于是在冷静的时空中让我回想到了很多的知识,不知你们是怎样过来的,真心希望我的这篇数据库总结能够让我们都有一 ...
- Autocad 2012 win7(64位)启动时一直卡在acmgd.dll处的解决方案
安装Autocad 2012后,激活成功后,无法正常启动,一直卡在加载acmgd.dll 通过Procmon监控后发现加载C:\Windows\fonts\AdobeFnt11.lst处出错, 通过命 ...
- this的安身之处
在JavaScript的大千世界中,this对象就像一个行踪不定.居无定所的浪子一般,它的生活仿佛可以随处而安,而内心却又似有着笃定的坚守,它就是这么有趣! 初学JavaScript时的我们,多多少少 ...
- OO方式下,ALV TREE和ALV GRID的不同之处
作为大部分报表程序的基础,ALV GRID差不多是每个ABAP开发者必须了解和掌握的内容,因此网上也不乏相关资料,而ALV TREE的应用相对较少,中文资料也就比较少见了.实际上,ALV TREE和A ...
- Windows 64位下装Oracle 11g,PLSQL Developer的配置问题,数据库处显示为空白的解决方案
安装pl sql 后,若下图的数据库处为空.则需要安装32位的客户端,说明pl sql不支持64位客户端连接. 解决办法: 1.下载32位Oracle客户端,并安装 2.设置PLSQL Develo ...
随机推荐
- Android(java)学习笔记141:SQLiteDatabase的query方法参数分析
public Cursor query (boolean distinct, String table, String[] columns, String selection, String[] se ...
- mysql sqlmap 注入尝试
假设注入点为 http://www.abc.com/news.php?id=12 //探测数据库信息 sqlmap -u http://www.abc.com/news.php?id=12 –dbs ...
- 5.CentOS6.6安装git
额,因为公司的项目存放在gitlab上,所以要求员工必须会使用git 这里简单说下git在 linux下的安装,使用的说明,我会单开一篇文章来写 1.首先卸载掉CentOS6.6自带的1.7.1版本的 ...
- Adapter 适配器模式
将一个类的接口转换成客户希望的另外一个接口.Adapter模式使得原本由于接口不兼容而不能一起工作的那些类可以在一起工作. 目标接口(Target):客户所期待的接口.目标可以是具体的或抽象的类,也可 ...
- js_BOM_05
1.下拉级联 |-select的API |-如何获得选中的option? |-如何创建option? |-如何将option添加到select? |-如何移 ...
- 黑色遮罩引导蒙版 CSS实现方式
一.微云的实现 网站有一些改动的时候,为了让用户熟知新的操作位置,往往会增加一个引导,常见的方式就是使用一个黑色的半透明蒙版,然后需要关注的区域是镂空的. 然后上周五我去微云转悠的时候,也看到了引导层 ...
- BS开发平台,一小时搞定功能强大的统计分析页面
BS开发平台,一小时搞定功能强大的统计分析页面,拥有强大的功能和详细的权限控制. 1.组织数据,分析需求(实际耗时大约20分钟) 2.建立需要的业务数据表(大致10分钟)3. 运行代码工具,生产需要 ...
- Android colors.xml
<?xml version="1.0" encoding="utf-8"?><resources> <color name=&qu ...
- Candence下对“跨页连接器(off-page connector)”进行批量重命名的方法
parts.ports.alias等等均可以在“属性编辑器(Property Editor)”中进行查看编辑,并通过复制到Excel等表格软件来进行批量修改.之后再粘贴回去的方法进行批量编辑.但是“跨 ...
- 浅析ASP.NET的状态保持
ASP.NET的状态保持:1.viewstate:隐藏域,记录服务器端控件的状态,适用于页面不关闭的情况下多次与服务器交互,页面自己给自己传值:文本框的改变事件.IspostBack也依赖viewst ...