HTML5文件API
HTML5文件API使HTML5页面内的JavaScript可以加载和处理本地文件系统中的文件。通过HTML5文件API,JavaScript可以在本地处理文件,例如压缩,编码或者加密文件,或者以较小的块上传文件。当然,HTML5文件API引发了一些安全问题。此HTML5文件API教程将说明如何使用文件API,以及HTML5文件API的安全约束是什么。
HTML5文件API的核心对象
HTML5文件API包含以下核心对象:
FileList
File
Blob
FileReader
"文件File"对象代表本地文件系统中的文件。
FileList对象代表本地文件系统中文件的列表。例如,目录内的文件列表。
" Blob"对象表示一个二进制大对象(BLOB),用于保存本地文件系统中单个文件的内容。
在以下各节中,我们将看到如何使用这些文件API对象。
选择文件
在HTML5文件API可以从本地文件系统访问文件之前,用户必须选择要授予访问权限的文件。出于安全原因,选择文件是通过<< input type =" file">HTML元素完成的。这是一个
input`元素的例子:
<input type="file" >
仅靠" input"元素是不够的。我们也需要一个" onchange"监听器。看起来是这样的:
<input type="file" onchange="readFiles(event)" >
输入元素包含一个浏览按钮。单击该按钮后,将向用户显示一个文件对话框。在该文件对话框中,用户可以选择一个文件。通过作为参数传递给它的"事件"对象,选定的文件将对" onchange"侦听器可用。
选择多个文件
为了使用户能够选择多个文件,请将" multiple"属性插入" input"元素。看起来是这样的:
<input type="file" onchange="readFiles(event)" multiple>
通过拖放选择文件
我们可以将HTML5文件API与HTML5拖放功能结合使用。这样,用户可以将文件从他/她的计算机上(浏览器外部)的文件浏览器拖到HTML页面内的"放置区域" HTML元素上。 HTML页面可以检测何时通过JavaScript删除文件。
这是一个代码示例,显示了如何设置拖放区HTML元素,以便我们可以检测何时将文件拖到其上:
<div id="fileDropZone" > Drag file in here </div> <script> function drop(event) { evt.stopPropagation(); evt.preventDefault(); var fileList = event.dataTransfer.files; // access files via 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>
在拖放区HTML元素(示例开头的div)上,将两个函数dragOver()
和drop()
设置为拖放事件监听器。
当文件被放到拖放区HTML元素上时,将调用drop()
函数。拖放到放置区元素上的文件列表可以在event.dataTransfer.files对象(FileList对象)中找到。
并非必须使用dragOver()
函数。它仅显示被拖动的文件已复制。这通过拖动的文件图标显示。
访问所选文件所需的其余代码与通过" input"元素选择文件时的代码相同。我们将在以下各节中看到外观。
设置拖放区HTML元素的样式可能是个好主意,以使用户清楚他们可以将文件拖到其上以及拖放区的边界其中等。使它更短。
访问所选文件
用户选择一个或者多个文件后,可以通过两种方式访问所选文件。
访问所选文件的第一种方法是访问"输入"字段的"文件"属性。这是一个例子:
var inputField = document.getElementById('theFileInput'); var selectedFiles = inputField.files; for(var i=0; i<selectedFiles.length; i++) { var file = selectedFiles[i); }
访问所选文件的第二种方法是通过"输入"字段上的" onchange"侦听器功能。通过作为参数传递给侦听器函数的event
对象可以访问选定的文件。这是同时显示一个input元素和一个onchange侦听器函数的示例:
<input type="file" onchange="readFiles(event)" multiple> <script> function readFiles(event) { var fileList = event.target.files; } </script>
event.target.files对象是FileList对象。它包含选定文件的列表作为"文件"对象。如果仅选择一个文件,则此列表仅包含一个对象。这是显示如何迭代文件列表的示例:
<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()
这四个函数均以"文件"对象或者"斑点"对象为参数。
如前所述,可以从" FileList"对象获得" File"对象。
" Blob"对象代表文件的一部分(或者全部)。我们可以从File
对象创建Blob
对象,如下所示:
var theFile = fileList[0]; // a File from a FileList var from = 3; var to = 9; var blob = theFile.slice(from, to); // create Blob
" from"索引表示文件中要包含在" Blob"中的第一个字节的索引。 " to"索引表示将不包含在" Blob"中的第一个字节的索引。因此,如果如上例中的" to"索引为9,则索引为8的字节是要包含在" Blob"中的最后一个字节。
创建一个FileReader
要使用FileReader
,必须首先创建FileReader
对象。这是创建FileReader
对象的方法:
var reader = new FileReader();
一旦创建了FileReader,我们就可以在其上调用各种读取功能。
以文本形式加载文件
为了将文件加载为文本,我们可以使用HTML5文件API中的FileReader对象。这是通过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) { // result contains loaded file. console.log(loadedEvent.target.result); } reader.readAsText(theFile); } </script>
该文件被加载到loadAsText()函数中。首先创建一个FileReader对象。
其次,在FileReader对象上设置一个onload事件处理函数。文件加载完成后,将调用此事件处理函数。
第三,以File为参数调用FileReader上的readAsText()函数。这开始文件的加载。文件加载完成后,将调用" onload"事件处理程序。
将文件作为文本切片加载
我们可以加载文本的一部分,而不是将整个文件作为文本加载。这是一个名为" loadAsTextSlice()"的示例函数,该函数显示了如何使用HTML5文件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,并在FileReader实例上设置一个onload处理程序。
第三,使用Blob
对象作为参数调用FileReader
的readAsText()
函数。这开始读取文件。读取文件切片后,将调用onload事件处理函数。来自文件的文本切片可在loadedEvent.target.result
变量中找到。
将文件作为数据URL加载
也可以将文件作为数据URL加载。可以使用JavaScript将数据URL设置为img
元素上的源(src
)。这是一个名为loadAsUrl()
的JavaScript函数,该函数显示如何使用HTML5文件API将文件作为数据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事件处理程序。第三,在FileReader上调用readAsDataURL()函数。文件加载完成后,将调用onload
事件处理函数。作为参数传递给onload事件处理函数的事件对象的event.target.result属性包含编码为数据URL的文件。现在,我们可以将要加载并编码的文件设置为要显示图像的img元素的src属性值。
将文件加载为ArrayBuffer
FileReader对象的readAsArrayBuffer()函数可用于读取文件作为ArrayBuffer。一个" ArrayBuffer"代表一个任意长度的数据缓冲区。我们不能直接在ArrayBuffer中操作数据。相反,我们必须创建一个" DataView"对象,该对象可以以不同类型(例如,大小为8位,16位或者32位)访问" ArrayBuffer"中的数据。
这是将文件读取为" 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); //gets first byte of ArrayBuffer //... process rest of dataView ... } reader.readAsArrayBuffer(theFile); }
在这里,我们可以了解有关DataView
对象的更多信息。
通过提取上传文件
可以通过JavaScript AJAXfetch()
函数上传通过HTML5 File API访问的文件。这是一个通过fetch()
上传文件的样子的例子:
<form id="theForm"> <input type="file" id="fileField" > <input type="button" value="Upload" onclick="upload(event)"> </form> <script> function upload(event) { console.log("Uploading..."); const fileField = document.getElementById("fileField"); const formData = new FormData(); formData.append('test', 'testValue'); formData.append('selectedFile', fileField.files[0]); fetch('https://mydomain/upload', { method: 'PUT', body: formData }) .then((result) => { console.log('Success:', result); }) ; } </script>
监视文件加载进度
HTML5文件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 + "%)"); }
传递给进度侦听器函数的进度事件对象包含一个名为" lengthComputable"的布尔属性。如果此属性的值为" true",则可以计算已加载了总文件量。上面显示了如何进行。
浏览器对HTML5 File API的支持
根据" caniuse.com",大多数浏览器都很好地支持HTML5文件API。一些浏览器不支持File
构造函数,但是我们不需要。