Ajax获取图片的两种方式
2017-08-10 21:00
363 查看
在Web项目中,我们可能遇到需要利用Ajax来获取图片的情况。因为客户端处理的是图片文件的二进制流,所以可利用Blob和File API来将图片转为URL,赋值给img的src属性来解决这个问题。本文总结Ajax获取图片的两种方式,即针对XMLHttpRequest Level 1和Level 2给出解决方案。(注意:若无说明,下文中所有xhr都代表XMLHttpRequest 对象)。PS:最近想到这种需求,于是阅读一些资料,整了一天,写了本篇文章。如有错误,请不吝指正。题外话:写博客贵在坚持呀!!!
首先给出html结构,因为重点讲Ajax,所以用一个很简单的例子来说明,页面只有一个button和一个img。
因为Ajax要和后台交互,此处将使用Node.js完成后台的逻辑,逻辑同样很简单。只需对
Ajax请求图片的两种方式
首先公共代码如下:
XMLHttpRequest level 1(兼容旧浏览器):利用
该方法关键点是把响应文本转为二进制数据,利用字符串的
XMLHttpRequest level 2:设置xhr的responseType属性,指定为
从中可以看出,代码量大大减少,语法简洁而清晰。
总结:两种方式各有各的有点,方法一兼容性好,方法二清晰简洁。具体用那种,还看各位的想法了。
最后,给出几篇关于XMLHttpRequest的优秀文章:
1. 你真的会使用XMLHttpRequest吗?
2. XMLHttpRequest Level 2 使用指南
首先给出html结构,因为重点讲Ajax,所以用一个很简单的例子来说明,页面只有一个button和一个img。
<!--login.html的其他代码省略 --> <input type="button" id="btn"> <!--获取的图片将在此显示--> <img id="preview">
因为Ajax要和后台交互,此处将使用Node.js完成后台的逻辑,逻辑同样很简单。只需对
/和
/upload做处理即可。Ajax将请求
/upload的内容。当请求时,发送给客户端图片。代码如下:
var http=require('http'); var fs=require('fs'); http.createServer((req,res)=>{ console.log(`${req.method}:${req.url}`); if(req.url=='/'){ res.writeHead(200,{'Content-Type':'text/html,charset=utf-8'}); fs.createReadStream('login.html').pipe(res); }else if(req.url=='/upload'){ if(req.method.toLowerCase()=='get'){ fs.readFile('images/captcha.0953f.png',(err,file)=>{ res.setHeader('Content-Length',file.length); console.log(file.length); res.writeHead(200,{'Content-Type':'image/png'}); res.end(file); }) }else{ res.end('success'); } }else{ fs.readFile('.'+req.url,(err,file)=>{ if(err){ res.writeHead(404); res.end('Not found!'); } fs.createReadStream('.'+req.url).pipe(res); }) } }).listen(3000);
Ajax请求图片的两种方式
首先公共代码如下:
window.onload=function(){ var btn=document.getElementById('btn'); btn.onclick=function(){ sendRequest(); } }
XMLHttpRequest level 1(兼容旧浏览器):利用
overrideMimeType()方法,将xhr设置为
xhr.overrideMimeType('text/plain;charset=x-user-defined');。其中
text/plain表示把响应作为普通文本来处理;
charset=x-user-defined表示使用用户自定义的字符集,以告诉浏览器不要去解析数据,直接返回未处理过的字节码。此步骤必须,不可忽略。之后就可以通过
xhr.responseText取得响应文本,然后将其转为二进制数据,传递给Blob构造函数。而后,通过
FileReader的
readAsDataURL()方法创建URL赋值给图片的src属性即可。具体代码如下:
function sendRequest(){ var xhr=new XMLHttpRequest(); xhr.onload=function(){ if(xhr.status>=200 && xhr.status<300){ var binStr = this.responseText; //console.log(this.response==this.responseText);//true var arr = new Uint8Array(binStr.length); for(var i = 0, l = binStr.length; i < l; i++) { arr[i] = binStr.charCodeAt(i); //arr[i] = binStr.charCodeAt(i) & 0xff; } //console.log(binStr.charCodeAt(0).toString(16)); //console.log(arr[0].toString(16)); var blob=new Blob([arr.buffer],{type:'image/png'}) loadImage_file(blob); }else{ console.log('error'); } } xhr.open('get','/upload',true); //兼容老浏览器。必须,以文本格式接受,字符集自定义 xhr.overrideMimeType('text/plain;charset=x-user-defined'); xhr.send(null); } function loadImage_file(blob){ var fr=new FileReader(); fr.readAsDataURL(blob); fr.onload=function(e){ var preview=document.getElementById('preview'); preview.src=e.target.result; } }
该方法关键点是把响应文本转为二进制数据,利用字符串的
charCodeAt(index)方法可以得到index位置的字符码,遍历整个字符串将其编码保存至
Uint8Array中,而后传递给Blob来重构URL。关于
arr[i] = binStr.charCodeAt(i) & 0xff;,表示在每个字符的两个字节之中,只保留后一个字节,将前一个字节扔掉。原因是浏览器解读字符的时候,会把字符自动解读成Unicode的0xF700-0xF7ff区段。但因为我用的是
Uint8Array,它会自动截取低8位,所以做不做与运算也就无所谓了。
XMLHttpRequest level 2:设置xhr的responseType属性,指定为
blob(或
ArrayBuffer,如设置为
ArrayBuffer,还要转
Uint8Array,然后转成
blob),例如,
xhr.responseType='blob';。这样就可以通过
xhr.response来获取该blob对象。注意不能用
xhr.responseText来获取,因为该属性只在响应类型是“text”时有效,强行获取只会得到错误:
Uncaught InvalidStateError: Failed to read the 'responseText' property from 'XMLHttpRequest': The value is only accessible if the object's 'responseType' is '' or 'text' (was 'blob').。该方法响应blob对象,所以无需对响应再做其他处理,只需传给
FileReader的
readAsDataURL()就可以了。代码如下:
function sendRequest(){ var xhr=new XMLHttpRequest(); xhr.onload=function(){ if(xhr.status>=200 && xhr.status<300){ var blob = this.response; //loadImage_file()方法与前面相同 loadImage_file(blob); }else{ console.log('error'); } } xhr.open('get','/upload',true); xhr.responseType='blob'; xhr.send(null); }
从中可以看出,代码量大大减少,语法简洁而清晰。
总结:两种方式各有各的有点,方法一兼容性好,方法二清晰简洁。具体用那种,还看各位的想法了。
最后,给出几篇关于XMLHttpRequest的优秀文章:
1. 你真的会使用XMLHttpRequest吗?
2. XMLHttpRequest Level 2 使用指南
相关文章推荐
- ajax获取返回值两种方式
- Ajax的基础请求以及获取JSON的两种解析方式
- Android根据图片文件名获取它的资源ID 的两种方式
- Android根据图片文件名获取它的资源ID 的两种方式
- php获取远程图片的两种 CURL方式和sockets方式获取远程图片
- Android从网络上获取图片的两种方式
- 从网络上获取图片的两种方式讲解:thread+handle和AsyncTask方式
- 原生ajax和iframe框架实现图片文件上传的两种方式
- 安卓获取图片缩略图的两种方式
- 获取远程文章内容时,显示图片的两种方式
- [Android]获取拍照完的图片的数据两种方式
- Android之从网络上获取图片的两种方式讲解:thread+handle和AsyncTask方式
- Android根据图片文件名获取它的资源ID 的两种方式
- php获取远程图片的两种:CURL方式和sockets方式获取远程图片
- java 两种上传文件(图片)方式(app通过流上传)+服务端获取方式(多图上传,普通文本上传,图片压缩)
- jfreechart获取图片的两种方式
- java 实现BufferedImage和ImageReader两种方式获取图片宽高、判断图片类型、获取图片大小工具类代码以及测试响应结果
- ajax获取数据的两种方式
- 安卓获取图片缩略图的两种方式