在h5出来之前,图片预览对于前端来说是非常有局限性的,需要配合后端实现,通过后端拿到地址后显示,h5出来后,图片预览变为可能,h5提供了新的file上传api-URL和FileReader。

FileList

先来说下FileList,FileReader和URL的预览都需要先获取到FileList对象(类数组),file类型表单在上传文件时,通过javascript获取到该表单的files,files就是FileList对象,FileList对象获取计算机上文件的存储信息与数据。

files简单代码如下

file.addEventListener('change',function(e){
	var files = this.files||e.target.files;
	console.log(files);
});
复制代码

files在console.log打印如下,里面包含了图片最后更改时间,图片大小类型等等;



URL

URL是window下的一个对象,URL.createObjectURL是一个静态方法,通过FileList对象数据创建一个url地址(类似于http格式),我的理解是相当于一个地址的引用,性能相对FileReader来说要好一点,而且不会丢失参数,优先选择的预览方式。

FileReader

FileReader是一个构造函数,通过实例化一个对象可以读取FileList对象数据并转换为base64,base64格式为data:......,base64在一些奇奇怪怪的手机可能会丢失掉文件格式参数导致显示不出来,转换为base64格式体积增加1/3,体积太大的图片会使页面cpu上升,建议通过服务器转成一个url地址。base64在预览并且要canvas剪辑的时候用得多一点。

下面通过一个简单的例子来说明,上代码直接撸起来

html

<!--上传容器-->
<div class="upload">
	<input type="file" class="file" multiple="multiple"
	accept="image/jpeg,image/png,image/gif"/>
</div>
<!--图片容器-->
<div class="content">
</div>
复制代码

上传文件的两种选择方式

var file = document.querySelector('.file'),//上传input
    content = document.querySelector('.content'),//盛放图片容器
	select,//上传方式
	filter = { 
		"jpeg": "/9j/4",
		"png": "iVBORw",
		"gif": "R0lGOD"
	}; //验证格式,base64包含图片格式的,
	但在个别奇葩手机图片格式丢失

file.addEventListener('change',function(e){
	var files = this.files||e.target.files;
	console.log(files)
        if(files){//支持html5的api
            if(window.URL||window.webkitURL||window.mozURL){
            	select.src(files);//方式一,优先选择
            }else if(window.FileReader){
            	select.base64(files);//方式二
            }
	}
});	
复制代码

两种方式的实现,通过闭包只暴露方法不暴露私有变量,按照策略模式,把实现代码和逻辑代码分离开,通过add增加方法。策略模式听起来可能有点难理解,但看代码应该就明白了。

select=(function(){
    var way ={
    	src:url,//方式一
    	base64:base64,//方式二
    	add:function(key,callback){
    		this[key]=callback;
    	}//增加上传预览方法
    };
    //方式一
    function url(files){
    	for(var a=0,f=files.length;a<f;a++){
    		var url = window.URL || window.webkitURL || window.mozURL;
    		var src = url.createObjectURL(files[a]);
    		preview(src);//预览图片
    	}
    };
    //方式二
    function base64(files){
    	for(var a=0,f=files.length;a<f;a++){
    		var obj = new FileReader();
    		obj.readAsDataURL(files[a]);
    		obj.onload=function(e){
    			console.log(validate(e.target.result))
    			if(!validate(e.target.result)){
    				alert('格式错误');
    				return;
    			}
    			preview(e.target.result);//预览图片
    		}
    	}
    };
    return way;
    })();
复制代码

这部分只是把复用的代码封装成为那个函数调用分别是验证图片格式和预览图片

//验证格式
function validate(data){
    for(var item in filter){
    	if(data.indexOf(filter[item])>-1){
    		return true;
    	}
    }
    return null
}
//预览图片
function preview(src){
    var img = document.createElement('img');
    img.src=src;
    img.style.cssText="max-width:100px;"
    content.appendChild(img);
}
复制代码

h5新的api使得纯前端也能实现图片预览功能,以上只是简单的分析,关于h5上传其实还有很多小坑,未完待续......