File API的宗旨是为Web开发人员提供一种安全的方式,以便在客户端访问用户计算机中的文件,并更好地对这些文件执行操作。
HTML5虽然可以让我们访问本地文件系统,但是文件只有在用户触发了文件读取行为才能读取到File API,这通常在发生在表单文件选择和拖拽的情况下。
一. File API的兼容性
File API在各大主流浏览器中的支持情况如下图所示:
备注:图片转载自: http://www.ibm.com/developerworks/cn/web/1210_jiangjj_html5log/
浏览器对 File API 支持情况的更详细信息可以参考网站 http://caniuse.com/#search=File 。
可以用下面的方法检测当前浏览器是否支持File API:
function checkSupportFileAPI() {
if(window.File && window.FileList && window.FileReader) {
return true;
} else {
return false;
}
}
二. File对象的属性
FileAPI在表单中的文件输入字段的基础上,又添加了一些直接访问文件信息的接口。HTML5在DOM中为文件输入元素添加了一个file集合。在通过文件输入字段选择了一或多个文件时,files集合中将包含一组File对象,每个File对象对应着一个文件。每个File对象都有下列只读属性:
name : 本地文件系统的文件名;
size :文件的字节大小;
type :String类型,文件的MIME类型;
lastModifiedDate :String类型,文件最后被修改的时间。
在HTML5中,通过添加 multiple 属性,file控件内允许一次放置多个文件。控件内的每一个选择的文件都是一个file对象。
例子:通过监听change事件,并读取files集合就可以知道每个文件的信息:
<input type="file" name="" id="filesList" multiple>
<script type="text/javascript">
var filesList = document.getElementById("filesList");
filesList.addEventListener("change", function(e) {
var files = this.files,
i = 0,
len = 0;
if(files) {
len = files.length;
}
while(i < len) {
console.log(files[i].name + "( " + files[i].type + ", " + files[i].size + "bytes )");
i++;
}
});
</script>
选择三个文件后,console中输出如下:
a.jpg( image/jpeg, 1499704bytes )
b.png( image/png, 395511bytes )
c.jpg( image/jpeg, 1614001bytes )
三. FileReader对象
3.1 FileReader读取文件数据的方法
FileReader类型实现的是一种一部文件读取机制。可以把FileReader想象成XMLHttpRequest,区别只是它读取的是文件系统,而不是远程服务器。FileReader提供一个异步API,使用该API可以在浏览器主线程中异步访问文件系统,读取文件中的数据。为了读取文件中的数据,FileReader提供了如下几个方法:
readAsText(file|blob [, encoding]) :以纯文本形式读取文件,将读取到的文本保存在result属性中。第二个参数用于指定编码类型,可选。
readAsDataURL(file|blob) :读取文件并将文件以数据URI的形式保存在result属性中。
readAsBinaryString(file|blob) :读取文件并将一个字符串保存在result属性中,字符串中的每个字符表示一个字节。
readAsArrayBuffer(file|blob) :读取文件并将一个包含文件内容的ArrayBuffer保存在result属性中。
abort() :中断读取操作。
这些读取文件的方法为灵活地处理文件数据提供了极大的便利。例如,可以读取图像文件并将其保存为数据URI,一遍将其显示给用户;或者为了解析方便,可以将文件读取为文本形式。
3.2 FileReader的兼容性
实现了FileAPI的所有浏览器都支持readAsText()和readAsDataURL()方法。但是IE10 PR 2不支持readAsBinaryString()和readAsArrayBuffer()。IE9及其以下版本浏览器不支持FileReader API。
检查当前浏览器是否支持FileReader API的方法如下:
if(typeof FileReader == "undefined") {
alert("您的浏览器不支持FileReader API.");
} else {
var reader = new FileReader();
}
3.3 FileReader的事件
由于读取文件的过程是异步的,因此FileReader也提供了几个事件,常用的有:
progress() :数据读取中。
error() :数据读取出错时触发。
load() :数据读取成功完成时触发。
abort() :数据读取中断时触发。
loadstart() :数据读取开始时触发。
loadend() :数据读取完成时触发,无论成功或失败。
每过50ms左右,就回触发一次progress事件通过事件对象可以获得与XHR的progress事件相同的信息(属性):lengthComputable、loaded和total。每次progress事件中都可以通过FileReader的result属性读取到文件内容。
当无法读取文件时,就会触发error事件。触发error事件时,相关的信息将保存到FileReader的error属性中。这个属性将保存一个对象,该对象只有一个属性code,即错误码。这个错误码的属性值如下:
1:表示未找到文件;
2:表示安全性错误;
3:表示读取中断;
4:表示文件不可读;
5:表示编码错误。
文件加载成功后会触发load事件。如果发生了error事件,就不会发生load事件。
例子:
<input type="file" name="" id="filesList">
<div id="progress"></div>
<div id="output"></div>
<script type="text/javascript">
var filesList = document.getElementById("filesList");
filesList.addEventListener("change", function(e) {
var info = "",
output = document.getElementById("output"),
progress = document.getElementById("progress"),
files = this.files,
type = "default",
reader = new FileReader();
if(/image/.test(files[0].type)) {
reader.readAsDataURL(files[0]);
type = "image";
} else {
reader.readAsText(files[0]);
type = "text";
}
reader.onerror = function() {
output.innerHTML = "error code: " + reader.error.code;
};
reader.onprogress = function(event) {
console.log("lengthComputable: " + event.lengthComputable);
if(event.lengthComputable) {
progress.innerHTML = event.loaded + "/ " + event.total;
}
};
reader.onload = function() {
var html = "";
switch(type) {
case "image":
html = "<img src=\"" + reader.result + "\">";
break;
case "text":
html = reader.result.toString();
break;
}
output.innerHTML = html;
}
});
</script>
在这个例子中,读取了表单字段中选择的文件,并将其内容显示在页面中如果是图片类型的文件,则将其保存为数据URI,并显示出读取的内容;如果是文件而不是图片,则以字符串形式读取并显示其内容。