HTML5

来源:互联网 发布:php文档系统 编辑:程序博客网 时间:2024/04/29 22:55


HTML5时代的纯前端上传图片预览及严格图片格式验证函数

标签: javascripthtml5FileReader图片格式验证图片预览
2609人阅读 评论(8)收藏 举报
分类:
作者同类文章X
    作者同类文章X

      一、要解决什么样的问题?

      在写这个函数之前,有位童鞋在群里问如何纯前端严格验证图片格式。这在html5时代之前,那是不可能实现的,必须要上传到后台,由后台脚本读取文本流后进一步验证。这样就造成了一定的服务器资源浪费。但是html5时代,这个工作我们完全可以交给前端来做了。

      另一方面,html5时代,许多我们原来的图片预览方案都失效了。究其原因,其实是现代浏览器出于对用户隐私的保护,file控件不再提供真实的物理地址,而统一变成:C:\fakepath\xxx.xxx 这样的假地址。不过,天无绝人之路,虽然旧的方案失效了,但是html5还是给我们提供了其它的途径的。

      那么,以上的问题我们该怎么解决呢?这就要借助html5提供的File API了。这里我们需要要用到的API是“ FileReader ”。

      二、关于FileReader

      顾名思义,FileReader就是html5为我们提供的读取文件的api。它的作用就是把文本流按指定格式读取到缓存,以供js调用。

      FileReader有四种读取文件的方式,四种方式的区别如下:
      1. readAsBinaryString     ---- 将文件读取为二进制码

      2. readAsDataURL  ---- 将文件读取为 DataURL

      3. readAsText   ---- 将文件读取为文本

      4. readAsArrayBuffer
      ----将文件读取为ArrayBuffer

      因为还要做图片预览,所以我们这里将采用第二种readAsDataURL方式来读取文件。那么DataURL究竟是怎么样的一种格式呢?以下是截取的一个gif图片的DataURL格式。

      [plain] view plaincopyprint?在CODE上查看代码片派生到我的代码片
      1. data:image/gif;base64,R0lGODlhAQABAIAAAAAAAAAAACH...oJCAcGBQQDAgEAACH5BAEAAAAALAAAAAABAAEAQAICRAEAOw==  
      所谓的DataURL格式,其实就是:data:[文件格式];base64,[文本流base64编码]

      这种格式有什么好处呢?对于前端来说,最直观的好处就是,可以把它写进img标签的src,也可以写进css的background-image。这样就可以把一张图片直接塞进html代码或者css代码中,而不必再多一次http
      request。

      讲到这里,很多童鞋或许已经对有点眉目了,接着往下看。

      三、图片格式验证方案

      做过后台验证文件格式的童鞋应该知道,许多文件格式,是有固定的文件头的(文件的文本流开头几个字节)。我们的JPEG、GIF、PNG等图片,也有这样的文件头。所以,我们现在就是要通过这个文件头来对图片格式进行严格验证,就在前端,纯JS,不需要借助任何后台脚本的帮助。

      刚刚说到,readAsDataURL方式读取的文件,会得到文件文本流的base64编码。所以,我们其实只需要对比一下base64编码的头几个字符就可以知道我们将要上传的文件格式是什么样的。经过我的多次验证,JPEG、GIF、PNG的DataURL编码格式如下:

      [plain] view plaincopyprint?在CODE上查看代码片派生到我的代码片
      1. jpg格式如下:  
      2. data:image/jpeg;base64,/9j/4...  
      3.   
      4. png格式如下:  
      5. data:image/png;base64,iVBORw...  
      6.   
      7. gif格式如下:  
      8. data:image/gif;base64,R0lGOD...  
      也就是说,jpeg图片的base64编码开头总是/9j/4,png的开头总是iVBORw,而gif的开头总是R0lGOD。所以,至此,我们的验证方案其实已经浮出水面了。

      四、图片上传预览及验证函数

      下面是综合上面说的所有知识我自己写的一个函数,在此提供给大家(演示DEMO):

      [javascript] view plaincopyprint?在CODE上查看代码片派生到我的代码片
      1. function previewImage(file, prvid) {  
      2.     /* file:file控件 
      3.      * prvid: 图片预览容器 
      4.      */  
      5.     var tip = "Expect jpg or png or gif!"// 设定提示信息  
      6.     var filters = {  
      7.         "jpeg"  : "/9j/4",  
      8.         "gif"   : "R0lGOD",  
      9.         "png"   : "iVBORw"  
      10.     }  
      11.     var prvbox = document.getElementById(prvid);  
      12.     prvbox.innerHTML = "";  
      13.     if (window.FileReader) { // html5方案  
      14.         for (var i=0, f; f = file.files[i]; i++) {  
      15.             var fr = new FileReader();  
      16.             fr.onload = function(e) {  
      17.                 var src = e.target.result;  
      18.                 if (!validateImg(src)) {  
      19.                     alert(tip)  
      20.                 } else {  
      21.                     showPrvImg(src);  
      22.                 }  
      23.             }  
      24.             fr.readAsDataURL(f);  
      25.         }  
      26.     } else { // 降级处理  
      27.         if ( !/\.jpg$|\.png$|\.gif$/i.test(file.value) ) {  
      28.             alert(tip);  
      29.         } else {  
      30.             showPrvImg(file.value);  
      31.         }  
      32.     }  
      33.   
      34.     function validateImg(data) {  
      35.         var pos = data.indexOf(",") + 1;  
      36.         for (var e in filters) {  
      37.             if (data.indexOf(filters[e]) === pos) {  
      38.                 return e;  
      39.             }  
      40.         }  
      41.         return null;  
      42.     }  
      43.   
      44.     function showPrvImg(src) {  
      45.         var img = document.createElement("img");  
      46.         img.src = src;  
      47.         prvbox.appendChild(img);  
      48.     }  
      49. }  
      使用示例:
      [html] view plaincopyprint?在CODE上查看代码片派生到我的代码片
      1. <input id="files" type="file" onchange="previewImage(this, 'prvid')" multiple="multiple">  
      2. <div id="prvid">预览容器</div>  

      五、兼容性

      本函数兼容chrome、firefox、ie6+。
      但由于ie9以下的浏览器并不支持FileReader,所以,在验证图片格式的时候,会有一个降级处理。

      0 0