HTML5图片上传图片实时预览,通过DataURL将图片压缩“嵌入”到HTML中,优化图片的加载速度和执行效率。
传统的方式预览图片主要有两种方法:
① 先上传图片到服务器,服务器返回URL,再将URL放在img标签上来达到预览图片的目的。
优点:开发方便,原理简单,实现容易。
缺点:功能支持有限,需要先上传再下载图片,需要额外占用一个HTTP会话,中间很耗时耗流量。
② 通过FLASH控件来实现实时预览图片。
优点:能够实现本地预览、压缩图片后上传,能够支持早期IE浏览器。
缺点:需要安装Flash 控件,手机端不支持。
通过DataURL实现本地图片预览:
优点:
① 直接生成Base64图片编码,不需要引入外部资源,不占用额外连接。
② 由于不占用额外连接,图片加载速度很快。
③ 几乎所有浏览器都支持。
④ dataURL和Blob对象可以互相转换,很方便图片上传。
缺点:
① DataURL形式的图片不会被浏览器所缓存,不过可以结合css一起使用,css资源文件是可以被浏览器缓存的。
② 很占CPU内存资源,不适合大量使用,可以在可接受的范围内适量使用。
③ 不支持早期IE浏览器。
分析利弊,可以看出DataURL很适合做前端图片预览。
代码实践:
Html部分:
…
<input type="file" accept="image/*" id="fileImage"/>
…
<img id="preview" src=""/>
Js部分:
/**
* Created by cjbi on 2017/8/21.
*/
//获取input document对象
var fileInput = document.querySelector("#fileImage");
//监听input改变事件
fileInput.addEventListener("change", function (e) {
//获取文件流
var file = e.target.files[0];
if (file) {
//创建文件读取对象
var reader = new FileReader();
//创建图片对象
var image = new Image(),
//创建cavas对象
canvas = document.createElement("canvas"),
//获取2D绘图对象
ctx = canvas.getContext('2d');
//文件加载完成后执行执行
reader.onload = function (e) {
var url = reader.result;//读取到的文件内容.这个属性只在读取操作完成之后才有效,并且数据的格式取决于读取操作是由哪个方法发起的.所以必须使用reader.onload
image.src = url;//reader读取的文件内容是base64,利用这个url就能实现上传前预览图片
};
//图片加载完成后执行执行
image.onload = function () {
var w = image.naturalWidth,//获取图片原始宽度
h = image.naturalHeight;//获取图片原始高度
canvas.width = 120;//cavas画板宽度
canvas.height = 120;//cavas画板高度度
// drawImage 参数说明:
//context.drawImage(img,sx,sy,swidth,sheight,x,y,width,height);
// 参数 描述
// img 规定要使用的图像、画布或视频。
// sx 可选。开始剪切的 x 坐标位置。
// sy 可选。开始剪切的 y 坐标位置。
// swidth 可选。被剪切图像的宽度。
// sheight 可选。被剪切图像的高度。
// x 在画布上放置图像的 x 坐标位置。
// y 在画布上放置图像的 y 坐标位置。
// width 可选。要使用的图像的宽度。(伸展或缩小图像)
// height 可选。要使用的图像的高度。(伸展或缩小图像)
ctx.drawImage(image, 0, 0, w, h, 0, 0, 200, 200);
//展示预览图片
document.querySelector("#preview").src = cavas.toDataURL();
}
reader.readAsDataURL(file);
}
}, false);
选定图片上传,console观察img标签src属性变化:
<img id="preview" src="data:image/gif;base64,R0lGODlhAwADAIAAAP///..此处有省略…//8zMzCH5BAAAAAAALAAAAAADAAMAAAIEBHIJBQA7"/>
可以看出src属性生成了一串Base64编码,这就是DataURL形式的图片了。
DataURL如何转Blob对象:
其实File也是属于Blob对象,转换为Blob对象后,可以使用Ajax上传图像文件了。
/**
* dataURL转换成Blob的方法 created by cjbi
* @param dataURL
* @returns {*}
*/
function dataURLtoBlob(dataURL) {
var arr = dataURL.split(','), mime = arr[0].match(/:(.*?);/)[1],
bstr = atob(arr[1]), n = bstr.length, u8arr = new Uint8Array(n);
while (n--) {
u8arr[n] = bstr.charCodeAt(n);
}
return new Blob([u8arr], {type: mime});
}
总结:在这个例子中,DataURL的使用是完全符合场景的。它避免了让这个小小的预览图片独自产生一次次HTTP请求。而且用户体验上也上升了新的高度。