h5上传文件-预览篇二

1,106 阅读2分钟

项目中遇到的情况是一次性上传多张图片预览,我那时是把图片转base64预览,但问题来了,涉及到异步的东西会有点小坑。 代码基础不会详细讲,想看基础可以移步上一篇我写的h5上传文件-预览篇

举个例子: 我们一次性要上传的图片顺序和大小如下图,

代码如下

html

<input type="file" multiple="multiple" class="upload_file"/><br/><br/>
<a href="javascript:;" class="upload_btn">上传</a>
<div class="box"></div>

js

var arr_files =[],//发给服务器的图片对象
    upload_file = document.querySelector('.upload_file'),//图片上传文本
    box= document.querySelector('.box'),//图片显示容器
    upload_btn = document.querySelector('.upload_btn');//上传按钮
    upload_file.addEventListener('change',function(e){
    	select.base64(this.files);//base64方式预览
});
//预览图片
function preview(base64_arr){
    for(var i=0,b=base64_arr.length;i<b;i++){
    	var img =document.createElement('img');
    	img.src=base64_arr[i].base64;
    	img.style.cssText="width:100px;"
    	box.appendChild(img);				
    }
	
}

重点代码如下

select=(function(){
    var way ={
        base64:base64,
        add:function(key,callback){
            this[key]=callback;
        }//增加上传预览方法
    };
    function base64(files){
    	for(var a=0,f=files.length;a<f;a++){//一次多张图片上传循环遍历
            var read = new FileReader();//实例化对象
            read.readAsDataURL(files[a]);//读取FileList对象
            read.onload=function(e){//读取完成返回base64(this.result)
        	preview(base64_arr);
        }
    	}
    };
    return way;
})();

但上面这种方式会有问题的,转base64需要先用FileReader实例化对象再去读取,要等到onload加载完毕才得到base64,但js的事件,定时器,ajax,src地址加载等等都是异步获取,那有可能因为图片的大小不同导致加载的时间有差异,小图会先加载完显示,大图会在最后面显示,并不是我们需要的结果。结果有可能是反过来的!

有想过用计数的方式,这种方式也是node异步经常用的方式,但计数的方式只能知道最后结束了,并不能改变上传的顺序,用promise也不能解决,promise的实例方法then比异步队列先执行的,promise.all方法也还是找不到。 解决的办法是通过闭包缓存for循环的顺序,创建一个数组按照这个顺序添加图片的base64,最后在一次性添加到页面上。

function base64(files){
    	var base64_arr =[],//存放每一张图的base64图的FileList对象
    	for(var a=0,f=files.length;a<f;a++){//一次多张图片上传循环遍历
            var read = new FileReader();//实例化对象
            read.readAsDataURL(files[a]);//读取FileList对象
            read.onload=(function(a){//闭包缓存a
            	return function(e){//读取完成返回base64(this.result)
            		base64_arr[a]={base64:this.result};//保存每次图片的base64
            		if(base64_arr.length==files.length-1){//
                		preview(base64_arr);
            		}
            	}
            })(a)
    	}
    };

这个是图片上传遇到的一个小坑吧,后面还有还有....,未完待续....!