JS移动端/H5同时选择多张图片上传并使用canvas压缩图片
最近在做一个H5的项目,里边涉及到拍照上传图片的功能以及识别图片的功能,这里对识别图片的功能不做赘述,不属本文范畴。我在做完并上线项目后,同事跟我提了一个要求是可不可以同时选择多张图片上传,我做的时候的想法是如果给file表单加了multiple属性就没有办法调用手机的摄像头拍照了,如果不加,就无法同时选择多张图片,于是我就照实跟同事说了这个情况。但回头一想,单张图片可以上传,那多张图片呢?于是就有了本文的内容。
HTML5定义了FileReader作为文件API的重要成员用于读取文件,根据W3C的定义,FileReader接口提供了读取文件的方法和包含读取结果的事件模型。
FileReader的实例拥有4个方法,其中3个用以读取文件,另一个用来中断读取。下面的表格列出了这些方法以及他们的参数和功能,需要注意的是,无论读取成功或失败,方法并不会返回读取结果,这一结果存储在result属性中。
readAsText:该方法有两个参数,其中第二个参数是文本的编码方式,默认值为UTF-8。这个方法非常容易理解,将文件以文本方式读取,读取的结果即是这个文本文件中的内容。
readAsBinaryString:该方法将文件读取为二进制字符串,通常我们将它传送到后端,后端可以通过这段字符串存储文件。
readAsDataURL:这是例子程序中用到的方法,该方法将文件读取为一段以data:开头的字符串,这段字符串的实质就是DataURL,DataURL是一种将小文件直接嵌入文档的方案。这里的小文件通常是指图像与html等格式的文件。
FileReader还包含了一套完整的事件模型,用于捕获读取文件时的状态,下面这个表格归纳了这些事件。
文件一旦开始读取,无论成功或失败,实例的result属性都会被填充。如果读取失败,则result的值为null,否则即是读取的结果,绝大多数的程序都会在成功读取文件的时候,抓取这个值。
了解了H5提供的FileReader后,我们就使用FileReader来实现同事选择多张图片并上传。
首先,在HTML加入一个file表单,并设置其为multiple(浏览器在对multiple、disabled、checked、selected等这类属性进行解析时,只要这些属性存在,默认的就会被解析成true,甭管你设置的是disabled=true或者disabled=false亦或是disabled="",如果不想这些属性起作用,唯有用js来remove掉这些属性,除非你不设置这些属性。),并设置accept="image/*"用以只能选择图片类型的文件,代码如下:
接下来就到了js上场了:
//图片上传 varfile={ upload:function(e){ varself=this; varfiles=e.target.files; vartype=files[0].type.split('/')[0]; if(type!='image'){ alertMsg('请上传图片'); return; } //varsize=Math.floor(file.size/1024/1024); //if(size>3){ //alert('图片大小不得超过3M'); //return; //}; for(vari=0;ithis.height){ h=1000; varscale=this.width/this.height; h=h>this.height?this.height:h; w=h*scale; } else{ w=1000; varscale=this.width/this.height; w=w>this.width?this.width:w h=w/scale; } varanw=document.createAttribute("width"); varanh=document.createAttribute("height"); if(this.width>this.height){ anw.value=h; anh.value=w; } else{ anw.value=w; anh.value=h; } canvas.setAttributeNode(anw); canvas.setAttributeNode(anh); if(this.width>this.height){ ctx.translate(h,0); ctx.rotate(90*Math.PI/180) ctx.drawImage(this,0,0,w,h); ctx.restore(); } else{ ctx.drawImage(this,0,0,w,h); } dataURL=canvas.toDataURL('image/jpeg'); //回调函数用以向数据库提交数据 self.callback(dataURL); }; }; } }, event:function(){ $("#upload").change(function(e){ file.upload(e); }); }, callback:function(dataURL){ $.ajaxSettings.async=false;//这里必须将ajax的异步改为同步才可以把返回并保存在隐藏域中的图片地址取出同时加在地址栏中作为参数一并传入下一个页面,这样做的目的是因为返回的图片地址不是一个json数组,而是单个的json字符串,所以只能将返回的图片地址json字符串拼接在一起作为参数传到下一个页面 $.post(url,dataURL,function(res){//将base64图片流的图片通过后台转换成普通的图片路径并上传至服务器 varimgUrl=$("#hiddenImgUrl").val(); if(res.success){ $(".loading").hide(); if(imgUrl!=""){ $("#hiddenImgUrl").val(imgUrl+"|"+res.imgUrl);//中间加一个|是为了到下一个页面便于将传过去的图片地址参数转换为数组 }else{ $("#hiddenImgUrl").val(res.imgUrl); } varimgUrl=$("#hiddenImgUrl").val(); window.location.href="apply.html?imgUrl="+imgUrl; }else{ alert(res.message); } },"json"); }, init:function(){ this.event(); } } file.init();
由于在通过post向服务器上传时采用了同步的方式,所以我在写项目的过程中,老是无法实现加载中的动画效果,并且把加载中的动画效果放在reader.onloadstart方法中依旧不起作用,最后只能放在了$("#upload").change(function(e){})方法中,代码如下:
event:function(){ $("#upload").change(function(e){ $(".loading").show(); file.upload(e); }); }
以上是同时上传多张图片并将图片传入下一个页面继续进行后续操作,那么如何在同时上传完多张图片后在本页再预览这些图片呢?其实方法也是很简单的,上边callback函数里边的$.post的返回值里就包含了上传至服务器后的图片路径,将这些路径赋给img标签的src,然后再插入到页面中就OK了,代码如下:
callback:function(dataURL){ $.post(url,dataURL,function(res){//将base64图片流的图片通过后台转换成普通的图片路径并上传至服务器 if(res.success){ $(".loading").hide(); varresult='
以上在预览图片时由于不需要跳转,不需要传入返回的所有图片的路径作为参数,所以也就不需要将ajax的异步设置为同步了。
以上所述是小编给大家介绍的JS移动端/H5同时选择多张图片上传并使用canvas压缩图片,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对毛票票网站的支持!