File API的宗旨是为Web开发人员提供一种安全的方式,以便在客户端访问用户计算机中的文件,并更好地对这些文件执行操作。
HTML5虽然可以让我们访问本地文件系统,但是文件只有在用户触发了文件读取行为才能读取到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; } }
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类型实现的是一种一部文件读取机制。可以把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,一遍将其显示给用户;或者为了解析方便,可以将文件读取为文本形式。
实现了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(); }
由于读取文件的过程是异步的,因此FileReader也提供了几个事件,常用的有:
progress()
:数据读取中。 error()
:数据读取出错时触发。 load()
:数据读取成功完成时触发。 abort()
:数据读取中断时触发。 loadstart()
:数据读取开始时触发。 loadend()
:数据读取完成时触发,无论成功或失败。 每过50ms左右,就回触发一次progress事件通过事件对象可以获得与XHR的progress事件相同的信息(属性):lengthComputable、loaded和total。每次progress事件中都可以通过FileReader的result属性读取到文件内容。
当无法读取文件时,就会触发error事件。触发error事件时,相关的信息将保存到FileReader的error属性中。这个属性将保存一个对象,该对象只有一个属性code,即错误码。这个错误码的属性值如下:
文件加载成功后会触发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,并显示出读取的内容;如果是文件而不是图片,则以字符串形式读取并显示其内容。