【JavsScript】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 | varxhr = newXMLHttpRequest();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) {    varbinStr = this.responseText;    for(vari = 0, len = binStr.length; i < len; ++i) {      varc = binStr.charCodeAt(i);      //String.fromCharCode(c & 0xff);      varbyte = 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; varxhr = newXMLHttpRequest();xhr.open('GET', '/path/to/image.png', true);xhr.responseType = 'arraybuffer'; xhr.onload = function(e) {  if(this.status == 200) {    varbb = newBlobBuilder();    bb.append(this.response); // Note: not xhr.responseText     varblob = bb.getBlob('image/png');    ...  }}; xhr.send(); | 
此外ArrayBuffer是二进制数据通用的固定长度容器。如果您需要原始数据的通用缓冲区,ArrayBuffer 就非常好用,但是它真正强大的功能是让您使用 JavaScript 类型数组创建底层数据的“视图”。实际上,可以通过单个 ArrayBuffer 来源创建多个视图。例如,您可以创建一个 8 位整数数组,与来自相同数据的现有 32 位整数数组共享同一个 ArrayBuffer。底层数据保持不变,我们只是创建其不同的表示方法。
| 1 2 3 4 5 6 7 8 9 10 11 | varxhr = newXMLHttpRequest();xhr.open('GET', '/path/to/image.png', true);xhr.responseType = 'arraybuffer'; xhr.onload = function(e) {  varuInt8Array = newUint8Array(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. varxhr = newXMLHttpRequest();xhr.open('GET', '/path/to/image.png', true);xhr.responseType = 'blob'; xhr.onload = function(e) {  if(this.status == 200) {    varblob = this.response;     varimg = 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 | functionsendText(txt) {  varxhr = newXMLHttpRequest();  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 | functionsendForm() {  varformData = newFormData();  formData.append('username', 'johndoe');  formData.append('id', 123456);   varxhr = newXMLHttpRequest();  xhr.open('POST', '/server', true);  xhr.onload = function(e) { ... };   xhr.send(formData);} | 
由form数据初始化formData
| 1 2 3 4 5 | <formid="myform"name="myform"action="/server">  <inputtype="text"name="username"value="johndoe">  <inputtype="number"name="id"value="123456">  <inputtype="submit"onclick="return sendForm(this.form);"></form> | 
| 1 2 3 4 5 6 7 8 9 10 11 12 13 | functionsendForm(form) {  varformData = newFormData(form);   formData.append('secret_token', '1234567890'); // Append extra data before send.   varxhr = newXMLHttpRequest();  xhr.open('POST', form.action, true);  xhr.onload = function(e) { ... };   xhr.send(formData);   returnfalse; // Prevent page from submitting.} | 
同时可以包含文件上传
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | functionuploadFiles(url, files) {  varformData = newFormData();   for(vari = 0, file; file = files[i]; ++i) {    formData.append(file.name, file);  }   varxhr = newXMLHttpRequest();  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 | <progressmin="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 | functionupload(blobOrFile) {  varxhr = newXMLHttpRequest();  xhr.open('POST', '/server', true);  xhr.onload = function(e) { ... };   // Listen to the upload progress.  varprogressBar = 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; varbb = newBlobBuilder();bb.append('hello world'); upload(bb.getBlob('text/plain')); | 
4)上传字节:xhr.send(ArrayBuffer)
| 1 2 3 4 5 6 7 8 9 | functionsendArrayBuffer() {  varxhr = newXMLHttpRequest();  xhr.open('POST', '/server', true);  xhr.onload = function(e) { ... };   varuInt8Array = newUint8Array([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 | varxhr = newXMLHttpRequest();xhr.onload = function(e) {  vardata = 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; functiononError(e) {  console.log('Error', e);} varxhr = newXMLHttpRequest();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) { ... };         varbb = newBlobBuilder();        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; functionupload(blobOrFile) {  varxhr = newXMLHttpRequest();  xhr.open('POST', '/server', true);  xhr.onload = function(e) { ... };  xhr.send(blobOrFile);} document.querySelector('input[type="file"]').addEventListener('change',function(e) {  varblob = this.files[0];   const BYTES_PER_CHUNK = 1024 * 1024; // 1MB chunk sizes.  const SIZE = blob.size;   varstart = 0;  varend = BYTES_PER_CHUNK;   while(start < SIZE) {     // Note: blob.slice has changed semantics and been prefixed. Seehttp://goo.gl/U9mE5.    if('mozSlice'inblob) {      varchunk = blob.mozSlice(start, end);    } else{      varchunk = blob.webkitSlice(start, end);    }     upload(chunk);     start = end;    end = start + BYTES_PER_CHUNK;  }}, false); })();
 | 
http://mozilla.com.cn/post/34886/
【JavsScript】XMLHttpRequest2的进步之处的更多相关文章
- 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时的我们,多多少少 ... 
- JavsScript+dom
		JavsScript+dom DOM(兼容性) 用于操作文档树 1.帮助我们找到标签 直接查找 间接查找 getElementById getElementsByTageName 2.标签操作 内容: ... 
- OO方式下,ALV TREE和ALV GRID的不同之处
		作为大部分报表程序的基础,ALV GRID差不多是每个ABAP开发者必须了解和掌握的内容,因此网上也不乏相关资料,而ALV TREE的应用相对较少,中文资料也就比较少见了.实际上,ALV TREE和A ... 
随机推荐
- android 62  手机存储目录的划分
			android下应用程序的路径和javase不同,应用程序的数据要保存自己的文件夹里面 > > getFileDir(); 获取自己的文件夹 /data/data/包名(应用程序的名字)/ ... 
- 自定义String类,并且实现在STL容器中添加自定义的类型
			13.44 编写标准库string类的简化版本,命名String.你的类应该至少有一个默认构造函数和一个接受C风格字符串指针参数的构造函数.使用allocator为你的String类分配所需内存. 1 ... 
- CentOS 7.2 修改主机名
			1.临时修改主机名 hostname 主机名 重新连接shell,就可以,这种方式,只能修改临时的主机名,当重启机器后,主机名称又变回来了. 2.永久修改主机名 hostnamectl set-hos ... 
- NDK开发之字符串操作
			在JNI中,Java字符串被当作一个引用来处理.这些引用类型并不像原生C字符串一样可以直接使用,JNI提供了Java字符串与C字符串之间转换的必要函数,因为Java字符串对象是不可变的(如果对这里有异 ... 
- CentOS7添加第三方源
			CentOS由于很追求稳定性,所以官方源中自带的软件不多,因而需要一些第三方源,比如EPEL.ATrpms.ELRepo.Nux Dextop.RepoForge等. EPEL EPEL即Extra ... 
- 使用Cache防止多人同时修改同一条信息
			Default.aspx: <a href="Default2.aspx?id=123&type=11ad">打开第二个页面id=123</a>&l ... 
- Jquery 限制文本框输入字数【转】
			<script type="text/javascript" src="js/jquery.min.js" ></script> < ... 
- Asp.net Mvc对比Php的4大误解
			一:asp.net技术已过时,Php技术更新 Asp.net mvc 5 发布于2014 夏天. 二:php开发者更多,所以更能得到帮助 2者对比犹如下图,会拿电锯的肯定多少会点锯子, 会用锯子的不一 ... 
- 【Windows】Windows中的数据类型以及命名
			一.大写标示符 Windows中的很多标识符都是以两个或者三个大写字母作为前缀的,且其后紧跟一个下划线.这些标识符都是常量数值,前缀表明该常量的一般类别.如下 前缀 常量 CS(Class Style ... 
- spring配置文件中属性mappingLocations、mappingDirectoryLocations
			http://blog.csdn.net/vacblog/article/details/7774173 
