HTML5文件API

时间:2020-01-09 10:34:38  来源:igfitidea点击:

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"&gtHTML元素完成的。这是一个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对象作为参数调用FileReaderreadAsText()函数。这开始读取文件。读取文件切片后,将调用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构造函数,但是我们不需要。