HTML5时代的纯前端上传图片预览及严格图片格式验证函数(转载)
原文地址:http://www.2cto.com/kf/201401/274752.html
一、要解决什么样的问题?
在写这个函数之前,有们童鞋在群里问如何纯前端严格验证图片格式。这在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格式。
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编码格式如下:
jpg格式如下:
data:image/jpeg;base64,/9j/4... png格式如下:
data:image/png;base64,iVBORw... gif格式如下:
data:image/gif;base64,R0lGOD...
也就是说,jpeg图片的base64编码开头总是/9j/4,png的开头总是iVBORw,而gif的开头总是R0lGOD。所以,至此,我们的验证方案其实已经浮出水面了。
四、图片上传预览及验证函数
下面是综合上面说的所有知识我自己写的一个函数,在此提供给大家:
function previewImage(file, prvid) {
/* file:file控件
* prvid: 图片预览容器
*/
var tip = "Expect jpg or png or gif!"; // 设定提示信息
var filters = {
"jpeg" : "/9j/4",
"gif" : "R0lGOD",
"png" : "iVBORw"
}
var prvbox = document.getElementById(prvid);
prvbox.innerHTML = "";
if (window.FileReader) { // html5方案
for (var i=0, f; f = file.files[i]; i++) {
var fr = new FileReader();
fr.onload = function(e) {
var src = e.target.result;
if (!validateImg(src)) {
alert(tip)
} else {
showPrvImg(src);
}
}
fr.readAsDataURL(f);
}
} else { // 降级处理
if ( !/\.jpg$|\.png$|\.gif$/i.test(file.value) ) {
alert(tip);
} else {
showPrvImg(file.value);
}
} function validateImg(data) {
var pos = data.indexOf(",") + 1;
for (var e in filters) {
if (data.indexOf(filters[e]) === pos) {
return e;
}
}
return null;
} function showPrvImg(src) {
var img = document.createElement("img");
img.src = src;
prvbox.appendChild(img);
}
}
使用示例:
<input id="files" type="file" onchange="previewImage(this, 'prvid')" multiple="multiple">
<div id="prvid">预览容器</div>
五、兼容性
本函数兼容chrome、firefox、ie6+ 。 但由于ie9以下的浏览器并不支持FileReader,所以,在验证图片格式的时候,会有一个降级处理。
HTML5时代的纯前端上传图片预览及严格图片格式验证函数(转载)的更多相关文章
- 利用html5 canvas实现纯前端上传图片的裁剪
今天跟大家分享一个前端裁剪图片的方法.许多网站都有设置用户头像的功能,用户可以选择一张本地的图片,然后用网站的裁剪工具进行裁剪,然后设置大小,位置合适的头像.当然,网上也有一些用js写的诸如此类裁剪的 ...
- 【小月博客】用HTML5的File API做上传图片预览功能
前段时间做了一个项目,涉及到上传本地图片以及预览的功能,正好之前了解过 html5(点击查看更多关于web前端的有关资源) 可以上传本地图片,然后再网上看了一些demo结合自己的需求,终于搞定了.(P ...
- HTML5 上传图片预览
html5出现之前如果需要上传图片预览 一般都是先上传到服务器然后远程预览 html5出现之后 有个filereader 解决了这问题 //选中图片之后 $("#fileAddPic&q ...
- HTML5上传图片预览
<!DOCTYPE html> <html> <head> <title>HTML5上传图片预览</title> <meta http ...
- jquery实现上传图片预览(需要浏览器支持html5)
jquery实现上传图片预览(需要浏览器支持html5) <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN&q ...
- HTML5上传图片预览功能
HTML5上传图片预览功能 HTML代码如下: <!-- date: 2018-04-27 14:41:35 author: 王召波 descride: HTML5上传图片预览功能 --> ...
- 通过HTML5 FileReader实现上传图片预览功能
原文:http://www.htmleaf.com/ziliaoku/qianduanjiaocheng/201706224590.html 在上传图片到服务器之前,我们希望可以预览一下要上传的图片. ...
- HTML5文件上传前本地预览
HTML5之FileReader的使用 HTML5定义了FileReader作为文件API的重要成员用于读取文件,根据W3C的定义,FileReader接口提供了读取文件的方法和包含读取结果的事件模型 ...
- java多图片上传--前端实现预览--图片压缩 、图片缩放,区域裁剪,水印,旋转,保持比例。
java多图片上传--前端实现预览 前端代码: https://pan.baidu.com/s/1cqKbmjBSXOhFX4HR1XGkyQ 解压后: java后台: <!--文件上传--&g ...
随机推荐
- jmeter安装部署、maven路径配置
jmeter下载地址: https://jmeter.apache.org/download_jmeter.cgi 解压文件 配置jmeter环境变量 (1)设置jmeter解压目录的JMETER_H ...
- android 报错: java.lang.NoClassDefFoundError: Failed resolution of: Landroid/support/v4/animation/AnimatorCompatHelper;
在使用SmartRefreshLayout时,报 java.lang.NoClassDefFoundError: Failed resolution of: Landroid/support/v4/a ...
- Python学习--两种方法爬取网页图片(requests/urllib)
实际上,简单的图片爬虫就三个步骤: 获取网页代码 使用正则表达式,寻找图片链接 下载图片链接资源到电脑 下面以博客园为例子,不同的网站可能需要更改正则表达式形式. requests版本: import ...
- 局域网电脑之间ping不通解决办法
局域网电脑之间ping不通一般都是防火墙的原因.解决办法有以下两种方法 1 第一种方法 1 找到Windows防火墙 2点击更改通知设置 3 关闭专用网络防火墙 现在就可以ping通这台机器了. 2 ...
- Tcp参数优化
net.core.netdev_max_backlog = 400000 #该参数决定了,网络设备接收数据包的速率比内核处理这些包的速率快时,允许送到队列的数据包的最大数目. net.core.opt ...
- mybatis 批量增加 Parameter '__frch_item_0' not found. Available parameters are [list]
当在mybatis用到foreach的时候,会报这个错误Parameter '__frch_item_0' not found. Available parameters are [list]会出现的 ...
- eclipspe导入hibernate的源代码
看图:
- Oracle 架构
- bzoj 2167: 公交车站
Description Z市交通不发达,所有公交路线覆盖的边竟然一个环也不包含,甚至该市的公交路线有可能会分为几个互不连通的块,这可真是不可思议.有一天,你突然听到一条消息,说你的M个同学被困在了Z市 ...
- C#中引用类型和值类型的区别,分别有哪些
C#的值类型包括:结构体(数值类型,bool型,用户定义的结构体),枚举,可空类型. C#的引用类型包括:数组,用户定义的类.接口.委托,object,字符串. 数组的元素,不管是引用类型还是值类型, ...