## File API **3、文件系统API** **3.1 File API** 在HTML5中新增了File API,可以让网页要求用户选择本地文件,并且读取这些文件的信息。选择的方式可以是HTML`<input>`元素,也可以是拖拽。 ``` <input type="file" id="photo"> var selectedFile = document.getElementById('photo'); var file = selectedFile.files[0]; //或者 file = selectedFile.files.item(0) ``` `selectedFile.files`返回一个FileList对象(有一个属性`length`,表示文件(File对象)个数),包含了一个或多个File对象,每个File对象都有自己的属性: - `file.name`:文件名,该属性只读。 - `file.size`:文件大小,单位为字节,该属性只读。 - `file.type`:文件的MIME类型,如果分辨不出类型,则为空字符串,该属性只读。 - `file.lastModified`:文件的上次修改时间,格式为时间戳。 - `file.lastModifiedDate` :文件的上次修改时间,格式为Date对象实例。 注意:如果要允许用户选取多个文件,需要加上`multiple`属性 ``` <input type="file" multiple /> ``` 一般情况下,我们会为input注册`change`事件,当文件被选择时,触发change。 ``` selectFile.addEventListener('change',function(){ var fileList = this.files; for(var i = 0; i < fileList.length; i++){ var file = fileList[i]; //或者 fileList.item(0); } },false); ``` **3.1.1 拖拽文件** 前面也说过,我们也可以通过拖拽方式选择文件。 ``` <div id="dropbox"></div> dropbox = document.getElementById('dropbox'); dropbox.addEventListener('dragenter',dragenter,false); dropbox.addEventListener('dragover',dragover,false); dropbox.addEventListener('drop',drop,false); ``` 在上面的代码中,ID为dropbox的div就是我们拖放目的区域。 拖放事件: ``` function dragenter(e){ e.stopPropagation(); e.preventDefault(); } function dragover(e){ e.stopPropagation(); e.preventDefault(); } function drop(e){ e.stopPropagation(); e.preventDefault(); var dt = e.dataTransfer; var files = dt.files; } ``` 在上面的代码中,参数e是一个事件对象,该参数的dataTransfer.files属性就是一个FileList对象,里面包含了拖放的文件。 注意:使用拖放事件时,必须阻止dragenter和dragover事件的默认行为,才能触发drop事件。 **3.1.2 FileReader API** 在上面我们知道如何获取文件信息,如何使用呢? 这时我们就要用到`FileReader API`了,此API用于读取文件,,即把文件内容读入内存。它的参数是File对象或Blob对象。 首先,我们需要实例化FileReader对象: ``` var reader = new FileReader(); ``` 对于不同类型的文件,FileReader提供了不同的方法来读取文件: - `readAsBinaryString(Blob|File)`:返回二进制字符串,该字符串每个字节包含一个0到255之间的整数。 - `readAsText(Blob|File, opt_encoding)`:返回文本字符串。默认情况下,文本编码格式是’UTF-8’,可以通过可选的格式参数,指定其他编码格式的文本。 - `readAsDataURL(Blob|File)`:返回一个基于Base64编码的data-uri对象。 - `readAsArrayBuffer(Blob|File)`:返回一个ArrayBuffer对象,即固定长度的二进制缓存数据。 我们来看一个显示用户所选图片的缩略图的例子: ``` <input type="file" onchange="handleFiles(this.files)"/> function handleFiles(files){ for(var i = 0; i < files.length; i++){ var file = files[i]; var imageType = /^image\//; if(!imageType.test(file.type)) continue; var img = document.createElement('img'); img.file = file; document.body.appendChild(img); var reader = new FileReader(); reader.onload = function(e){ img.src=e.target.result; }; reader.readAsDataURL(file); } } ``` 在上面的代码中,我们通过onchange去监听input内文件信息的变化,通过file.type判断用户选择的是否是图片,这里使用File对象的readAsDataURL()方法来返回一个data URL,然后使用onload事件监听文件是否读取完毕,如果读取完毕,我们就可以事件对象e来读取文件内容,也就是e.target.result; `readAsDataURL()`方法用于读取文本文件,它的第一个参数是File或Blob对象,第二个参数是前一个参数的编码方法,如果省略就默认为UTF-8编码。该方法是异步方法,一般监听onload件,用来确定文件是否加载结束,方法是判断FileReader实例的result属性是否有值。其他三种读取方法,用法与readAsDataURL方法类似。 注意:如果浏览器不支持FileReader,你也可以使用URL.createObjectURL(file)方法来创建一个data URL来显示图片缩略图。 FileReader API还有一个`abort`方法,用于中止文件上传。 FileReader API的其他监听事件 - onabort方法:读取中断或调用reader.abort()方法时触发。 - onerror方法:读取出错时触发。 - onload方法:读取成功后触发。 - onloadend方法:读取完成后触发,不管是否成功。触发顺序排在 onload 或 onerror 后面。 - onloadstart方法:读取将要开始时触发。 - onprogress方法:读取过程中周期性触发。