现在网上有很多成熟的图片上传的插件,由于之前对于图片上传未接触过,不了解其实现原理。网上查阅了相关资料,了解到其是基于FileReader Api。
众所周知,大家平时做兼容性都是为了兼容低版本浏览器,图片上传则恰恰相反。基于浏览器的安全策略,file标签在现代浏览器中已经获取不到真实路径。恰恰相反,低版本ie却能获取到真实物理路径。所以此功能是基于现代浏览器的解决方案。
FileReader就是html5为我们提供的读取文件的api。它的作用就是把文本流按指定格式读取到缓存,以供js调用。
FileReader有四种读取文件的方式:
1. readAsBinaryString读取为二进制码
2. readAsDataURL读取为 DataURL
3. readAsText读取为文本
4. readAsArrayBuffer
基于预览上传后图片的需求,需要将图片读取为DataURL。DataURL有固定格式,例如:data:[文件格式];base64,[文本流base64编码]。
- jpg格式:data:image/jpeg;base64,/9j/4...
- png格式: data:image/png;base64,iVBORw...
- gif格式:data:image/gif;base64,R0lGOD..
通过此格式我们就可以验证用户上传的图片类型。下面是本人写的简单demo:
html代码:
<input id="files" type="file" onchange="previewImage(this, ‘prvid‘)" multiple="multiple">
<div id="prvid">预览容器</div>
js代码:
function previewImage(file, prvid) {
/* file:file控件
* prvid: 图片预览容器
*/
var tip = "Expect jpg or png or gif!"; // 设定提示信息
var filters = {
"jpeg" : "/9j/4",
"gif" : "R0lGOD",
"png" : "iVBORw"
}
var prvbox = document.getElementById(prvid);
prvbox.innerHTML = "";
if (window.FileReader) { // html5方案
for (var i=0, f; f = file.files[i]; i++) {
var fr = new FileReader();
fr.onload = function(e) {
var src = e.target.result;
if (!validateImg(src)) {
alert(tip)
} else {
showPrvImg(src);
}
}
fr.readAsDataURL(f);
}
} else { // 降级处理
if ( !/\.jpg$|\.png$|\.gif$/i.test(file.value) ) {
alert(tip);
} else {
showPrvImg(file.value);
}
}
function validateImg(data) {
var pos = data.indexOf(",") + 1;
for (var e in filters) {
if (data.indexOf(filters[e]) === pos) {
return e;
}
}
return null;
}
function showPrvImg(src) {
var img = document.createElement("img");
img.src = src;
prvbox.appendChild(img);
}
}