| 
                                             简单记录下今早做H5上传中一些代码还有坑 
 
 一、展示 
 
 因为前端上传文件是必须通过form表单的,不能使用ajax,这样的话一个移动页面放入一个type为file的input真心不怎么好看,如下图,很挫有没有 
 
 
 
 
 
 解决办法找了下,PC上有些是把这个input换成flash,采用jquery的工具库比如uploadify来做,但是移动端大部分浏览器是不支持flash的。所以最后采用的办法还是用form表单的形式,只是把这个form和input的透明度设置为0,让它们和准备显示的内容同时在一个div中,显示的内容可以做成自己想要的样子。代码如下: 
 
 复制代码 <!DOCTYPE html> <html>     <head>         <meta charset="UTF-8">         <meta name="viewport" content="width=device-width,initial-scale=1.0,user-scalable=no">         <title></title>         <style>             div{width: 100%;}             .logo img{display:block; margin:0 auto;}             .upload{position: relative;width: 80px;height: 18px;line-height: 18px;background: #2fc7c9;text-align: center;                     color: #FFF;padding: 0px 5px;-webkit-border-radius: 2px;border-radius: 2px;                     margin: 0 auto;                     }             .upload form{width:100%;position:absolute; left:0; top:0;opacity:0; filter:alpha(opacity=0);}             .upload form input{width: 100%;}         </style>     </head>     <body>         <div class="logo">             <img src="img/1.jpg" />         </div>         <div class="upload">             <p>上传图片</p>             <form>                 <input type="file" />             </form>         </div>     </body> </html> 复制代码 样子如左图,这样展现就在“上传图片”这个p标签中,点击它就有选择file的效果 
 
   
 
 二、JS代码 
 
 我这边写的蛮简单的,只是用了下h5上传的的基本功能 
 
 html代码如下,action为要请求的路径,我这边做的是当文件发生改变时就上传修改头像,input标签的name属性不能省去,具体跟后端接口有关 
 
 <form id="uploadForm" enctype="multipart/form-data" method="post" action="XXXXXX">      <input type="file" name="imageFile" id="imageFile" onchange="fileSelected()" /> </form> 复制代码 var iMaxFilesize = 2097152; //2M window.fileSelected = function() {     var oFile = document.getElementById('imageFile').files[0];    //读取文件     var rFilter = /^(image\/bmp|image\/gif|image\/jpeg|image\/png|image\/tiff)$/i;     if (!rFilter.test(oFile.type)) {         alert("文件格式必须为图片");         return;     }     if (oFile.size > iMaxFilesize) {         alert("图片大小不能超过2M");         return;     }     var vFD = new FormData(document.getElementById('uploadForm')),    //建立请求和数据         oXHR = new XMLHttpRequest();     oXHR.addEventListener('load', function(resUpload) {         //成功     }, false);     oXHR.addEventListener('error', function() {         //失败     }, false);     oXHR.addEventListener('abort', function() {         //上传中断     }, false);     oXHR.open('POST', actionUrl);     oXHR.send(vFD); }; 复制代码   
 
 三、图片压缩 
 
 在开发中,特别是在移动端往往一张图片大小在3,4M左右,这样的图片上传会给服务器带来不少压力,同时也有不少接口对img的大小有所要求,比如不能超过200K,那手机相册的照片大多是见了鬼的,都上传不了。在html5的功能中,可以将图片压缩大小(尺寸)放到canvas画布上,然后截取canvas画布上的图片,转变为二进制的数据,通过blob进行再次压缩生成图片文件,这样手机上4M左右图片传到服务器上也就100K左右了。 
 
 <input type="file" name="imageFile" id="imageFile" onchange="fileSelected()" /> <form id="uploadForm" enctype="multipart/form-data" method="post" action="XXXXXX">      <input hidden="hidden" name="param" value="test" /> </form> 当文件改变时,对图片进行压缩上传 
 
 复制代码 window.fileSelected = function() {     var _this = $(this);     var file = this.files[0];     var rFilter = /^(image\/bmp|image\/gif|image\/jpeg|image\/png|image\/tiff)$/i;     if(!rFilter.test(file.type)) {         alert("文件格式必须为图片");         return;     }     /*开始进行网络加载*/     _this.css("display", "none");    //目的是为了屏蔽点击事件     var reader = new FileReader() , image = new Image() ,         canvas = document.createElement("canvas") , ctx = canvas.getContext("2d");     reader.onload = function() {        //文件加载完成         var url = reader.result;         image.src = url;     };     image.onload = function() {        //图片加载完成         var w = image.naturalWidth , h = image.naturalHeight ,             scale = 3;        //图片缩放比例,这里是把图片大小高宽均缩小3倍         canvas.width = w / scale;         canvas.height = h / scale;         ctx.drawImage(image, 0 , 0 , w , h ,             0 , 0 , canvas.width , canvas.height);         fileUpload();         };     reader.readAsDataURL(file);        //用文件加载器加载文件     function fileUpload() {        //文件上传方法         var quality = 0.3;        //图片的质量,这里设置的是0.3         var data = canvas.toDataURL("image/jpeg", quality);//获取画布图片,并且要jpg格式         data = data.split(',')[1];         data = window.atob(data);         var ia = new Uint8Array(data.length);         for(var i = 0; i < data.length; i++) {             ia[i] = data.charCodeAt(i);         }         var blob = new Blob([ia], {            //以上均为二进制参数处理,从而获取一个blob对象             type: "image/jpeg"         });         var fd = new FormData(document.getElementById("uploadForm"));         fd.append("XXX"  , blob , "upload.jpg");    //向form中加入图片数据,name属性是XXX,文件名是upload.jpg         var xhr = new XMLHttpRequest();         xhr.addEventListener('load', function(resUpload) {             _this.css("display", "");             //请求成功         }, false);         xhr.addEventListener('error', function(){             _this.css("display", "");             //请求失败         }, false);         xhr.addEventListener('abort', function(){             _this.css("display", "");             //上传终止         }, false);         xhr.open('POST', "http://XXXXXXXXXXXXX");//请求地址         xhr.send(fd);//发送     } }; 复制代码 关键代码 
 
 reader.readAsDataURL(file); 将文件读取为DataURL 
 
 canvas.toDataURL(type, encoderOptions);  实际上就是读取canvas画布上图片的数据。其默认是png格式,如果第一个参数type是image/jpeg的话,第二个参数encoderOptions就可以用来设置图片的压缩质量。 
 
 复制代码 var quality = 0.3;        //图片的质量,这里设置的是0.3 var data = canvas.toDataURL("image/jpeg", quality);//获取画布图片,并且要jpg格式 data = data.split(',')[1]; data = window.atob(data); var ia = new Uint8Array(data.length); for(var i = 0; i < data.length; i++) {     ia[i] = data.charCodeAt(i); } var blob = new Blob([ia], {            //以上均为二进制参数处理,从而获取一个blob对象     type: "image/jpeg" }); 复制代码 这一段代码的的目的是为了解码图片数据,然后返回一个Blob对象,对象的格式是jpg。aton其作用是做解码,因为图片格式的base64,该方法解码出来可能是一堆乱码,Uint8Array返回的是8进制整型数组。 
 
 Blob是存储二进制文件的容器,典型的Blob对象是一个图片或者声音文件,其默认是PNG格式。最后的blob就可以传给服务端了。 
 
 整理成一个插件,代码如下 
 
 复制代码 (function(window,undefind){     function imgUpLoad(options){         var defaults = {             inputId : "" ,        //输入框ID             formId : "" ,        //表单ID             paramName : "" ,        //输入框的name             requestUrl : "" ,     //请求的URL             imgSizeScale : 3 ,     //图片缩放比例             imgQuality : 0.3 ,    //图片质量             sucFun : undefind , //成功的回调函数             errFun : undefind , //失败的回调函数             abortFun : undefind     //上传取消的回调函数         };         var opts = $.extend(true , defaults , options || {}) ,             _this = document.getElementById(opts.inputId);         _this.addEventListener('change' , fileChange , false);             function fileChange() {             var file = _this.files[0];             var rFilter = /^(image\/bmp|image\/gif|image\/jpeg|image\/png|image\/tiff)$/i;             if(!rFilter.test(file.type)) {                 alert("文件格式必须为图片");                 return;             }             var reader = new FileReader() , image = new Image() ,                 canvas = document.createElement("canvas") , ctx = canvas.getContext("2d");             startFileLoad(reader , image , canvas , ctx);         }         function startFileLoad(reader , image , canvas , ctx){    //文件加载             reader.onload = function() {        //文件加载完成                 var url = reader.result;                 image.src = url;             };             image.onload = function() {        //图片加载完成                 var w = image.naturalWidth , h = image.naturalHeight;                 canvas.width = w / opts.imgSizeScale;                 canvas.height = h / opts.imgSizeScale;                 ctx.drawImage(image, 0 , 0 , w , h ,                     0 , 0 , canvas.width , canvas.height);                 fileUpload(canvas);                 };             reader.readAsDataURL(file);             }         function fileUpload(canvas){        //文件上传             var blob = getBlob(canvas);             var fd = new FormData(document.getElementById(opts.formId));             fd.append(opts.paramName  , blob , "upload.jpg");             var xhr = new XMLHttpRequest();             xhr.addEventListener('load', function(resUpload) {    //请求成功                 _this.style.display = "";                 if(opts.sucFun && typeof opts.sucFun === "function")        opts.sucFun(resUpload.currentTarget.response);             }, false);             xhr.addEventListener('error', function(){    //请求失败                 _this.style.display = "";                 if(opts.errFun && typeof opts.errFun === "function")        opts.errFun();             }, false);             xhr.addEventListener('abort', function(){    //上传终止                 _this.style.display = "";                 if(opts.abortFun && typeof opts.abortFun === "function")        opts.abortFun();             }, false);             xhr.open('POST', opts.requestUrl);//请求地址             xhr.send(fd);//发送         }         function getBlob(canvas){        //获取blob对象             var data = canvas.toDataURL("image/jpeg", opts.imgQuality);             data = data.split(',')[1];             data = window.atob(data);             var ia = new Uint8Array(data.length);             for(var i = 0; i < data.length; i++) {                 ia[i] = data.charCodeAt(i);             }             return new Blob([ia], {                             type: "image/jpeg"             });         }     }     window.imgUpLoad = imgUpLoad; })(window); 复制代码 
  
                                         |