一:FileList对象与file对象php
FileList对象表示用户选择的文件列表,在HTML4中,file控件内只容许放置一个文件,可是到了HTML5中,经过添加multiple属性,file控件内容许一次放置多个文件,控件内的每个用户选择的文件都是一个file对象,而FileList对象是file对象的列表;html
好比以下代码:html5
选择文件<input type="file" id="file" multiple size="80"/> <input type="button" onclick="ShowFileName();" value="文件上传"/>
咱们能够按住ctrl键选择多个文件;web
JS代码以下:chrome
function ShowFileName() { var files = document.getElementById("file").files; for(var i = 0; i < files.length; i+=1) { var file = files[i]; console.log(file); console.log(file.name); } }
咱们先打印下file对象有哪些属性,在safari截图以下:数据库
如上图能够看到有文件名(name)属性,文件大小(size)属性,最后修改时间,还有type属性等;canvas
二:Blob对象浏览器
在HTML5中,新增一个Blob对象,表明原始二进制数据,咱们上面提到的file对象也继承了这个Blob对象;安全
Blob对象有2个属性,size属性表示一个Blob对象的字节长度,type属性表示Blob的MIME类型,若是是未知类型,则返回一个空字符串。服务器
以下代码:
选择文件<input type="file" id="file" multiple size="80" accept="image/*"/> <input type="button" onclick="ShowFileType();" value="显示文件信息"/> 文件字节长度:<span id="size"></span><br/> 文件类型:<span id="type"></span>
JS代码以下:
function ShowFileType() { var file = document.getElementById("file").files[0]; var size = document.getElementById("size"); var type = document.getElementById("type"); // 显示文件字节长度 size.innerHTML = file.size; // 显示文件类型 type.innerHTML = file.type; console.log(file); }
咱们打印出file,以下图所示:
三:FileReader对象
FileReader对象有5种方法,其中四种用于读取文件,另外一种用来读取过程当中断,须要注意的是:不管读取成功与失败,方法并不会返回读取结果,而是将结果保存在result属性中。此对象也是异步的。
FileReader对象的方法以下:
readAsBinaryString(file): 这个方法将blob对象或文件中的数据读取为二进制字符串,一般咱们将它传送到服务器端,服务器端能够经过这段字符串存储文件。
readAsText(file,encoding): 以纯文本形式读取文件,将读取到的文本保存在result属性中,第二个参数用于指定编码类型,可选的。
readAsDataURL(file): 读取文件并将文件以数据URL的形式保存在result属性中。
readAsArrayBuffer(file): 读取文件并将一个包含文件内容的ArrayBuffer保存在result属性中。
FileReader对象的事件以下:
onabort: 数据读取中断时触发
onerror: 数据读取出错时触发
onloadstart: 数据读取开始时触发
onprogress: 数据读取中
onload: 数据读取成功完成时触发
onloadend: 数据读取完成时触发,不管成功或失败。
咱们能够先看看demo,如何使用FileReader对象中前面三个方法;注意:fileReader对象读取的数据都保存在result中,以下代码:
<p> <label>请选择一个文件:</label> <input type="file" id="file" /> <input type="button" value="读取图像" onclick = "readAsDataURL()"/> <input type="button" value="读取二进制数据" onclick = "readAsBinaryString()"/> <input type="button" value="读取文本文件" onclick = "readAsText()"/> </p> <div id="result"></div>
JS代码以下:
<script> var result = document.getElementById("result"); if(typeof FileReader == 'undefined') { result.innerHTML = "抱歉,你的浏览器不支持FileReader"; } // 将文件以Data URL形式进行读入页面 function readAsDataURL(){ // 检查是否为图像类型 var simpleFile = document.getElementById("file").files[0]; if(!/image\/\w+/.test(simpleFile.type)) { alert("请确保文件类型为图像类型"); return false; } var reader = new FileReader(); // 将文件以Data URL形式进行读入页面 reader.readAsDataURL(simpleFile); reader.onload = function(e){ console.log(this.result); result.innerHTML = '<img src="'+this.result+'" alt=""/>'; } } // 将文件以二进制形式读入页面 function readAsBinaryString(){ // 检查是否为图像类型 var simpleFile = document.getElementById("file").files[0]; if(!/image\/\w+/.test(simpleFile.type)) { alert("请确保文件类型为图像类型"); return false; } var reader = new FileReader(); // 将文件以二进制形式进行读入页面 reader.readAsBinaryString(simpleFile); reader.onload = function(e){ // 在页面上显示二进制数据 result.innerHTML = this.result; } } // 将文件以文本形式读入页面中 function readAsText(){ var simpleFile = document.getElementById("file").files[0]; var reader = new FileReader(); // 将文件以文本形式读入页面中 reader.readAsText(simpleFile); reader.onload = function(e){ result.innerHTML = this.result; } } </script>
如上代码,若是须要演示的话,能够复制代码到文本编辑器去,预览下便可,这里就不截图了;可是如上代码,在safari浏览器就不支持了~ 截图以下:
四:btoa方法与atob方法
在HTML5中,btoa方法与atob方法来支持base64编码,b能够被理解为一串二进制数据,a能够被理解为一个ASCLL码字符串,btoa的使用方法以下:
var result = window.btoa(data);
该方法用于将一串字符串进行base64编码处理,该方法使用一个参数,参数值由一串二进制数据组成的Unicode字符串,该方法返回编码后的base64格式的字符串。
atob方法使用以下所示:
var result = window.atob(data);
该方法用于将一串通过base64编码后的base64格式的字符串进行解码处理,该方法使用一个参数,参数值为一串通过base64编码后的字符串,方法返回通过解码后的一串由二进制数据组成的Unicode字符串;
浏览器支持:firefox,chrome,opera10.5+及IE10+
何时使用btoa方法呢?
当服务器端数据库中直接保存了是图片的二进制数据及图片文件的格式时,当咱们须要根据此二进制数据来渲染图片的时候很是有用;以下代码:
<p> <label>请选择一个文件:</label> <input type="file" id="file"/> <input type="button" value="读取图像" onclick = "readPicture()" id="btnReadPicture"/> </p> <div id="result"></div>
JS代码以下:
if(typeof FileReader == 'undefined') { result.innerHTML = "抱歉,你的浏览器不支持FileReader"; } function readPicture(){ // 检查是否为图像类型 var simpleFile = document.getElementById("file").files[0]; if(!/image\/\w+/.test(simpleFile.type)) { alert("请确保文件类型为图像类型"); return false; } var reader = new FileReader(); // 将文件以二进制文件读入页面中 reader.readAsBinaryString(simpleFile); reader.onload = function(f){ var result = document.getElementById("result"); var src = "data:" + simpleFile.type + ";base64," + window.btoa(this.result); result.innerHTML = '<img src ="'+src+'"/>'; } }
当咱们选择一张图像的时候,点击读取图像按钮便可生成一张图片,虽然此方法咱们还可使用咱们上面介绍的readAsDataURL的方法也能够直接读取图像,可是当服务器中直接是保存的是二进制文件的话,咱们能够直接使用btoa此方法生成图片便可;
下面咱们能够看看atob的demo以下:
咱们可使用canvas来绘制一张图片后,点击上传图片按钮后,首先经过canvas元素的toDataURL()方法获取该图片的url地址,最后获取该URL地址中的base64格式的字符串,最后使用atob方法将其解码为一串二进制数据,并将该二进制数据提交到服务器端;以下代码:
<input type="button" value="上传图片" onclick="imgSave()"/><br/> <canvas id="canvas" width="400" height="300"></canvas>
JS代码以下:
<script> var canvas; function draw(id) { canvas = document.getElementById(id); var context = canvas.getContext('2d'); context.fillStyle = 'rgb(0,0,255)'; context.fillRect(0,0,canvas.width,canvas.height); context.fillStyle = 'rgb(255,255,0)'; context.fillRect(10,20,50,50); } draw('canvas'); function imgSave(){ var data = canvas.toDataURL("image/png"); data = data.replace("data:image/png;base64,",""); var xhr = new XMLHttpRequest(); xhr.open("POST","uploadImg.php"); xhr.send(window.atob(data)); } </script>
uploadImg.php本身写;
下面咱们来作一个本地图片上传前预览效果,可是safari不支持,因此在作移动端的同窗可能很差了,特别是在IOS6下就不支持哦,应该还有其余办法能够解决的,咱们能够看看百度的插件,网址以下:
http://fex.baidu.com/webuploader/demo.html
以前我是作了一个上传本地图片以前预览效果,以下连接:
http://www.cnblogs.com/tugenhua0707/p/3568134.html
今天为了学习FileReader,咱们能够再来学习下;以前的本地上传图片预览的话,不支持IE10+, 且把页面放在服务器端在IE下会有bug,以下所示:
如上所示,在IE下 这个方法 document.selection.createRange() 不支持,所以为了修复这个bug和在IE10+以上的话,今天又特地研究了下, 在file控件下获取焦点状况下 document.selection.createRange() 将会拒绝访问,因此咱们要失去下焦点。咱们能够再加一句代码就能够支持了 file.blur();
IE10+的bug的话,咱们可使用html5的上面介绍的文件API来解决,先判断是否是IE,若是是的话,且小于10的话,使用滤镜的方法解决图片上传的问题,若是是其余浏览器的话,就使用html5的文件上传方法;可是safari没有处理好,缘由是safari不支持html5的fileReader的API,因此若是在移动端开发的图片,若是须要兼容IOS6和6+的话,请注意一下,并不支持~ 固然若是你们有更好的方案来支持IOS6的话,请留言,能够一块儿总结,一块儿学习~
五:上传图片以前预览效果demo(Safari不兼容)
1. 在标准浏览器下(IE10+)使用HTML5中文件API便可解决上传图片前预览效果;在这里有2中方案能够解决,第一种是使用文件API,以下代码:
function html5Reader(file) { var file = file.files[0]; var reader = new FileReader(); reader.readAsDataURL(file); reader.onload = function(e){ var pic = document.getElementById("img"); pic.src=this.result; } }
2. 第二种方案是使用 URL.createObjectURL(fileObj) 这个方法和canvas技术, 咱们先来看看 支持这个 URL.createObjectURL(fileObj) 的浏览器有哪些,咱们能够点击下面的链接查看:
http://caniuse.com/#search=createObjectURL/
实现代码以下:
function html5Reader(file) { var fileObj = file.files[0], img = document.getElementById("img"); // URL.createObjectURL safari不支持 img.src = URL.createObjectURL(fileObj); img.onload =function() { var data = getBase64Image(img); console.log(data); // 打印出base64编码 } } function getBase64Image(img) { var canvas = document.createElement("canvas"); canvas.width = img.width; canvas.height = img.height; var ctx = canvas.getContext("2d"); ctx.drawImage(img, 0, 0, img.width, img.height); var ext = img.src.substring(img.src.lastIndexOf(".")+1).toLowerCase(); var dataURL = canvas.toDataURL("image/"+ext); return dataURL;
}
HTML代码以下:
<input type="file" id="logo" name="logo" accept="image/*"> <img src= '' id="img"/> <div id="btn" style="margin-top:50px;font-size:40px;">btn</div> <canvas id="myCanvas"></canvas>
全部的JS代码以下:
<script> var EventUtil = { addHandler: function(element,type,handler) { if(element.addEventListener) { element.addEventListener(type,handler,false); }else if(element.attachEvent) { element.attachEvent("on"+type,handler); }else { element["on" +type] = handler; } } }; var btn = document.getElementById("btn"); var pic = document.getElementById("img"); function getBase64Image(img) { var canvas = document.createElement("canvas"); canvas.width = img.width; canvas.height = img.height; var ctx = canvas.getContext("2d"); ctx.drawImage(img, 0, 0, img.width, img.height); var ext = img.src.substring(img.src.lastIndexOf(".")+1).toLowerCase(); var dataURL = canvas.toDataURL("image/"+ext); return dataURL; } var ua = navigator.userAgent.toLowerCase(); EventUtil.addHandler(btn,'click',function(){ var file = document.getElementById("logo"); var ext=file.value.substring(file.value.lastIndexOf(".")+1).toLowerCase(); // gif在IE浏览器暂时没法显示 if(ext!='png'&&ext!='jpg'&&ext!='jpeg'){ alert("图片的格式必须为png或者jpg或者jpeg格式!"); return; } if(/msie ([^;]+)/.test(ua)) { var lowIE10 = RegExp["$1"]*1; if(lowIE10 == 6){ // IE6浏览器设置img的src为本地路径能够直接显示图片 file.select(); // 在file控件下获取焦点状况下 document.selection.createRange() 将会拒绝访问,因此咱们要失去下焦点。 file.blur(); var reallocalpath = document.selection.createRange().text; pic.src = reallocalpath; }else if(lowIE10 > 6 && lowIE10 < 10){ // IE7~9 IE10+按照html5的标准去处理 file.select(); // 在file控件下获取焦点状况下 document.selection.createRange() 将会拒绝访问,因此咱们要失去下焦点。 file.blur(); var reallocalpath = document.selection.createRange().text; // 非IE6版本的IE因为安全问题直接设置img的src没法显示本地图片,可是能够经过滤镜来实现 pic.style.filter = "progid:DXImageTransform.Microsoft.AlphaImageLoader(sizingMethod='image',src=\"" + reallocalpath + "\")"; // 设置img的src为base64编码的透明图片 取消显示浏览器默认图片 pic.src = 'data:image/gif;base64,R0lGODlhAQABAIAAAP///wAAACH5BAEAAAAALAAAAAABAAEAAAICRAEAOw=='; }else if(lowIE10 >= 10) { html5Reader(file); } }else { html5Reader(file); } }); function html5Reader(file) { var fileObj = file.files[0], img = document.getElementById("img"); // URL.createObjectURL safari不支持 img.src = URL.createObjectURL(fileObj); img.onload =function() { var data = getBase64Image(img); console.log(data); // 打印出base64编码 } /* var file = file.files[0]; var reader = new FileReader(); reader.readAsDataURL(file); reader.onload = function(e){ var pic = document.getElementById("img"); pic.src=this.result; }*/ } </script>