HTML5 File API允许页面使用Javascript来调用和处理本地文件系统的文件。通过HTML5 File API我们可以使用javascript来处理某个文件,例如对文件进行比较,编码,加密,更新等操作。由于涉及到本地文件的操作,HTML5 File API的安全问题也是被人们关注的重点问题。本文将介绍如何使用HTML5 File API,以及HTML5 File API的安全性问题。
HTML5 File API的核心对象
HTML5 File API包含以下的核心对象:
FileList
File
Blob
FileReader
File
对象代表本地文件系统中的一个文件。
FileList
对象代表本地文件系统中的一组文件。例如在某个目录或文件夹中的所有文件。
Blob
对象代表一个二进制大型对象(BLOB),BLOB是本地文件系统中的单个文件的数据。
下面将会接收如何使用这些File API对象。
选择一个文件
在HTML5 File API可以处理本地文件系统中的一个文件之前,用户需要执行一个选择文件的操作。由于安全的原因,通常是通过HTML的<input type="file">
元素来选择文件,就像下面的示例代码:
<input type="file" >
仅仅有input
元素是不够的,我们还需要添加一个onchange
的事件监听,下面是示例代码:
<input type="file" onchange="readFiles(event)">
文件输入域input[type='file']
包含一个“浏览”按钮,当用户点击这个按钮的时候,就会弹出一个文件对话框。在这个文件对话框中,用户可以对本地的文件进行选择,被选择的文件将会在onchange
事件监听的event
对象中作为参数传入。
选择多个文件
要使用户能够选择多个文件,可以在<input>
元素中添加一个multiple
属性,下面是一个示例代码:
<input type="file" onchange="readFiles(event)" multiple>
通过拖放选择文件
我们可以将HTML5 file API和HTML5元素拖放相结合来选择文件。这种选择文件的方式需要实现用户从本地电脑的文件系统中(在浏览器之外)拖拽一个文件到浏览器的HTML页面指定的放置区域。HTML页面能通过javascript来检测是否有文件被放置在指定的区域。
下面的代码是如何设置一个放置区域HTML元素,使它能够检测到是否有文件放置到它上面。
<div id="fileDropZone" > 请拖拽文件到这里 </div>
<script> function drop(event) { evt.stopPropagation(); evt.preventDefault(); var fileList = event.dataTransfer.files; // 通过fileList接收文件 } function dragOver(evt) { evt.stopPropagation(); evt.preventDefault(); evt.dataTransfer.dropEffect = 'copy'; } var dropZone = document.getElementById("fileDropZone"); dropZone.addEventListener("dragover", dragOver, false); dropZone.addEventListener("drop" , drop , false); </script>
dragOver()
和drop()
函数设置放置区域HTML元素的拖和放事件监听。
当一个文件被放置在放置区域的时候,drop()
函数将被调用。被放置在放置区域的文件列表可以通过event.dataTransfer.files
对象(一个FileList
对象)来找到。
dragOver()
函数是可选的。它仅用于文件被拖拽时的一个副本。它通过一个文件图标来显示。
剩下的代码是访问选择的文件,它和通过input
元素来选择一个文件后的操作是相同的。
在实际操作中最好为放置区域HTML元素设置一些样式,使用户能够明确的指定这里是可以拖拽放置的区域。
访问被选择的文件
当用户选择一个或多个文件之后,有两种方式访问这些被选择的文件。
第一种访问被选择文件的方式是访问input
元素的files
属性。下面是一个示例代码:
var inputField = document.getElementById('theFileInput'); var selectedFiles = inputField.files; for(var i=0; i<selectedFiles.length; i++) { var file = selectedFiles[i); }
第二种访问被选择文件的方式是通过input
元素的onchange
事件监听。被选择的文件会作为event
对象的参数被传入。下面是一个示例代码:
<input type="file" onchange="readFiles(event)" multiple>
<script> function readFiles(event) { var fileList = event.target.files; } </script>
event.target.files
对象是一个FileList
对象。它包含一组被选择的文件(File
对象)。如果只有一个文件被选择,这个列表中就只有一个对象。下面的实例代码说明了如何去迭代一组文件列表。
<input type="file" onchange="readFiles(event)" multiple>
<script> function readFiles(event) { var fileList = event.target.files; for(var i=0; i < fileList.length; i++ ) { var file = fileList[i]; // a File object console.log("i: " + i + " - " + file.name); } } </script>
FileList
是一组File
对象列表。File
对象用于访问文件。在下面的介绍中,你会看到通过javascript来加载文件的不同方法。
通过FileReader来加载文件
当用户选择了一个文件后。我们得到了一个文件的引用(例如通过onchange
事件)。我们可以通过FileReader
来读取这个文件。FileReader
对象有下面的一些方法可以用于读取文件:
readAsText()
readAsDataUrl()
readAsArrayBuffer()
上面的方法都使用一个File
对象或Blob
对象作为参数。
File
对象可以从FileList
对象中获取,前面已经介绍过。
Blob
对象代表部分或整个文件。你可以从File
对象中创建一个Blob
对象,下面是示例代码:
var theFile = fileList[0]; // 从FileList获取一个File对象 var from = 3; var to = 9; var blob = theFile.slice(from, to); // 创建Blob对象
上面的代码用slice
方法来分割一个文件,Blob
对象从文件的第3个字节开始,到第8个字节结束(不包含第9个字节)。
创建一个FileReader
要使用FileReader你先要创建FileReader
对象。创建FileReader
对象的方法如下:
var reader = new FileReader();
当FileReader
对象被创建之后,你就可以使用它来读取文件了。
将一个文件作为文本来加载
要将一个文件作为文本来加载,你可以使用HTML5 file API的FileReader
对象。下面是一个示例代码:
<input type="file" onchange="readFiles(event)" multiple>
<script> function readFiles(event) { var fileList = event.target.files; for(var i=0; i < fileList.length; i++ ) { loadAsText(fileList[i]); } } function loadAsText(theFile) { var reader = new FileReader(); reader.onload = function(loadedEvent) { // 返回包含被加载的文件 console.log(loadedEvent.target.result); } reader.readAsText(theFile); } </script>
文件在loadAsText()
函数中被加载。
上面的代码首先创建了一个FileReader
对象,然后在FileReader
对象上调用onload
事件,这个事件在文件被加载完毕之后被调用。
接着,FileReader
中的readAsText()
函数被调用,它使用一个File
对象作为参数。这里是加载文件的开始,当文件加载完毕,onload
事件将被调用。
加载部分文件
你可以只加载一个文件的某一部分,而不是整个文件。下面的loadAsTextSlice()
函数展示了如何使用HTML5 file API来加载文件的一部分内容。
function loadAsTextSlice(theFile) { var start = 3; var stop = 9; var blob = theFile.slice(start, stop); var reader = new FileReader(); reader.onload = function(loadedEvent) { console.log(loadedEvent.target.result); } reader.readAsText(blob); }
上面的例子通过File
对象的slice()
方法创建了一个Blob
对象。然后创建一个FileReader
对象,然后在它上面添加onload()
事件监听。
接下来FileReader
对象的readAsText()
被调用,它的参数是一个Bolb
对象。这是读取文件的开始,当这部分文件被读取完毕,onload()
方法就会被调用。要获取这部分被读取的文件,可以通过loadedEvent.target.result
来获取。
通过Data URL来加载文件
我们还可以通过data URL来加载一个文件。典型的例子是一个图片的数据,我们可以读取图片的数据,然后将这些数据设置到图片的src
属性中。下面的loadAsUrl()
函数展示了如何使用HTML5 file API将文件作为data URL进行读取。
function loadAsUrl(theFile) { var reader = new FileReader(); reader.onload = function(loadedEvent) { var image = document.getElementById("theImage"); image.setAttribute("src", loadedEvent.target.result); } reader.readAsDataURL(theFile); }
上面的代码中首先创建了一个FileReader
对象,然后在这个FileReader
对象上设置onload()
事件监听。当文件加载完毕,onload()
事件就会被触发。onload()
函数的参数是loadedEvent
,通过这个参数,我们可以获取被编码为data URL的文件数据,使用的是event.target.result
属性。在获取了编码的文件数据之后,我们就可以把这些数据设置为图片src
属性的值,这样图片就会被显示出来。
通过ArrayBuffer来加载文件
FileReader
对象的readAsArrayBuffer()
函数可以用于作为ArrayBuffer
来读取文件数据。一个ArrayBuffer
代表任意长度的缓冲区数据。你不能够直接在ArrayBuffer
中操作数据,你必须创建一个DataView
对象,该对象可以接收任意类型的ArrayBuffer
数据。
下面是一个例子:
function loadAsUrl(theFile) { var reader = new FileReader(); reader.onload = function(loadedEvent) { var arrayBuffer = loadedEvent.target.result; var dataView = new DataView(arrayBuffer, 0, arrayBuffer.byteLength); var byte = dataView.getUint8(0); //获取ArrayBuffer的第一个字节 //... 处理余下的dataView ... } reader.readAsArrayBuffer(theFile); }
关于DataView对象的更多资料,可以参考这里。
跟踪文件加载的进程
HTML5 file API允许我们跟踪文件加载的进程,这意味着我们可以知道当前文件加载了多少。要跟踪文件加载的进程,可以在FileReader
对象上添加onprogress
事件监听。
var reader = new FileReader(); reader.onprogress = function(progressEvent) { if(progressEvent.lengthComputable) { var percentLoaded = Math.round( ( progressEvent.loaded * 100) / progressEvent.total ); } console.log("total: " + progressEvent.total + ", loaded: " + progressEvent.loaded + "(" + percentLoaded + "%)"); }
传入到onprogress
事件中的progressEvent
参数包含一个布尔值的属性lengthComputable
。如果这个属性的值为true
,你就可以计算文件已经被加载了多少,具体操作就像上面代码的样子。
浏览器对HTML5 File API的支持
浏览器对HTML5 File API的支持可以通过caniuse.com来查看。IE8和IE9不支持它,其它的现代浏览器都支持HTML5 File API。但是有一些浏览器不支持File
对象的构造函数,这其实对使用没有什么影响。