在HTML5中,提供了一个关于文件操作的文件API,通过使用这个接口,对于从Web页面上访问本地文件系统的相关处理将会变得十分简单。
FileList对象与file对象
FileList对象表示用户选择的文件列表。在HTML5中,通过在file控件中添加multiple属性,可以使用控件内一次放置多个文件。控件内的每一个用户选择的文件都是一个file对象,而FileList对象则为这些file对象的列表,代表用户选择的所有文件。file对象具有两个属性:name属性表示文件夹名(不包含路径);lastModifiedDate属性表示文件的最后修改日期。
Blob对象
Blob表示二进制原始数据,它提供一个slice方法,可以通过该方法访问到字节内部的原始数据块。事实上,file对象也是继承了这个Blob对象。
Blob对象有两个属性:size属性表示一个Blob对象的字节长度;type属性表示Blob的MIME类型,如果是未知类型,则返回一个空字符串。
另外,HTML5中已经对file控件添加了accept属性,该属性让file控件只能打官腔某种类型的文件,该属性的使用方法如下:
<input type="file" id="file" accept="image/*"/>
示例1
为了方便,给jQuery提供访问FileList对象的功能,现扩展如下:
jQuery.fn.files = function() { return this[0].files; };
示例所用HTML页面如下:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml" lang="zh-cn" dir="ltr">
<head>
<meta charset="UTF-8" />
<title>文件API</title>
<script type="text/javascript" src="../js/jquery-1.6.4.js"></script>
<script type="text/javascript" src="../js/fileReader.js"></script>
</head>
<body>
<header>
<h1>文件API示例</h1>
</header>
<section>
<form id="filelist_sample" name="filelist_sample">
<label for="selectFiles">请选择文件:</label>
<input type="file" name="selectFiles" id="selectFiles" multiple="multiple"/>
<button type="button" id="showInfoBtn" name="showInfoBtn">显示文件信息</button><br/>
<button type="button" id="txtBtn" name="txtBtn">测试readAsText</button>
<button type="button" id="binBtn" name="binBtn">测试readAsBinaryString</button>
<button type="button" id="urlBtn" name="urlBtn">测试readAsDataURL</button>
</form>
<div id="fileContent"></div>
<footer>
<table id="info">
<caption>文件信息</caption>
<thead>
<tr>
<th>ID</th>
<th>文件名</th>
<th>文件类型</th>
<th>文件大小(KB)</th>
<th>最后修改日期</th>
</tr>
</thead>
<tfoot>
<tr>
<th>合计:</th>
<th><meter id="count" value="0" min="0" max="10">0</meter></th>
<th></th>
<th><meter id="sum" value="0" min="0" >0</meter></th>
<th><button type="button" id="clearBtn">清除信息</button></th>
</tr>
</tfoot>
</table>
</footer>
</section>
<footer>
<div id="console"></div>
</footer>
</body>
</html>
“显示文件信息”按钮的click事件代码如下:
$(function() { $("#showInfoBtn").click(function(event) { $("#clearBtn").click(); var fileObjs = $("#selectFiles").files(); var sum = 0, count = 1; var tbody = $("<tbody>"); for ( var index = 0; index < fileObjs.length; index++) { $("<tr>").append($("<td>").append("<meter>").val(count).text(count)) .append($("<td>").text(fileObjs[index].name)) .append($("<td>").text(fileObjs[index].type)) .append($("<td>").append($("<meter>").val(fileObjs[index].size).text(fileObjs[index].size / 1024))) .append($("<td>").text(fileObjs[index].lastModifiedDate)).appendTo(tbody); sum += fileObjs[index].size; count++; } $("td>meter, #sum").attr("max", 5 * 1024 * 1024); $("#info>thead").after(tbody); $("#count").attr("max", "10").val(fileObjs.length).text(fileObjs.length); $("#sum").val(sum).text(sum / 1024); }); });
“清除信息”按钮的click事件代码如下:
$(function() { $("#clearBtn").click(function(event) { $("#info>tbody, #fileContent, #console").empty(); $("#count, #sum").val(0).text(0); }); });
FileReader接口
FileReader接口主要用来把文件读入内在,并且读取文件中的数据。FileReader接口提供了一个异步API,使用该API可以在浏览器主线程中异步访问文件系统,读取文件中的数据。如下代码可以检测浏览器是否支持此接口:
if(typeof FileReader == "undefined") { alert("您的浏览器未实现FileReader接口!"); }
FileReader接口的方法
FileReader接口拥有4个方法,其中3个用以读取文件,另一个用来将读取过程中断。注意:无论读取成功或失败,方法并不会返回读取结果,这一结果存储在result属性中。
- readAsText(file[, encoding]):该方法有两个参数,其中第二个参数是文本的编码方式,默认值为UTF-8。该方法将文件以文本方式读取,读取的结果即是这个文本文件中的内容。
- readAsBinaryString(file):该方法将文件读取为二进制字符串,通常我们将它传送到后端,后端可以通过这段字符串存储文件。
- readAsDataURL(file):该方法将文件读取为一串Data URL字符串,该方法事实上是将小文件以一种特殊格式的URL地址形式直接读入页面。这里的小文件通常是指图像与html等格式的文件。
- abort():中断读取操作。
FileReader接口的事件
除了上述方法之外,FileReader接口还包含了一套完整的事件模型,用于捕获读取文件时的状态,这些事件如下:
- onloadstart:数据读取开始时触发。
- onprogress:数据读取中。
- onload:数据读取成功完成时触发。
- onloadend:数据读取完成时触发,无论成功或失败。
- onabort:数据读取中断时触发。
- onerror:数据读取出错时触发。
我们需要编写的代码主要都是在onprogress事件中,例如,可以用HTML5中的新增元素progress来显示大文件的读取完成百分比。
示例2
为方便使用FileReader接口,给jQuery增加几个函数如下:
var getFileReader = function(handler) { var reader = new FileReader(); reader.onloadstart = handler.loadStart; reader.onprogress = handler.progress; reader.onload = handler.load; reader.onloadend = handler.loadEnd; reader.onabort = handler.abort; reader.onerror = handler.error; return reader; }; jQuery.fn.readAsText = function(handler, encoding) { if (typeof encoding == "undefined") { encoding = "UTF-8"; } var files = this.files(); var reader = null; for ( var i = 0; i < files.length; i++) { reader = getFileReader(handler); reader.readAsText(files[i], encoding); } return this; }; jQuery.fn.readAsBinaryString = function(handler) { var files = this.files(); var reader = null; for ( var i = 0; i < files.length; i++) { reader = getFileReader(handler); reader.readAsBinaryString(files[i]); } return this; }; jQuery.fn.readAsDataURL = function(handler) { var files = this.files(); var reader = null; var imageHandler = function(event) { $("<img>").attr("src", event.target.result).appendTo("#fileContent"); }; for ( var i = 0; i < files.length; i++) { reader = getFileReader(handler); if (!/image\/\w+/.test(files[i].type)) { reader.readAsDataURL(files[i]); } else { reader.onload = imageHandler; reader.readAsDataURL(files[i]); } } return this; };
给上述函数传入的事件处理器函数代码如下:
$(function() { var createTag = function(txt) { $("#console").append($("<span>").text(txt).after("<br/>")); }; var handler = { load : function(event) { createTag("this is FileReader's onload event."); $("<p>").append(event.target.result).appendTo("#fileContent"); }, loadStart : function(event) { createTag("this is FileReader's onloadstart event."); }, loadEnd : function(event) { createTag("this is FileReader's onloadend event."); }, abort : function(event) { createTag("this is FileReader's onabort event."); }, error : function(event) { createTag("this is FileReader's onerror event."); }, progress : function(event) { createTag("this is FileReader's onprogress event."); } }; });
最后,三个按钮的click事件代码如下:
$(function() { $("#txtBtn").click(function(event) { $("#selectFiles").readAsText(handler); }); $("#binBtn").click(function(event) { $("#selectFiles").readAsBinaryString(handler); }); $("#urlBtn").click(function(event) { $("#selectFiles").readAsDataURL(handler); }); });