HTML5 - 操作本地文件

本篇文章的主要目的是介绍本地文件相关 API 的使用,好的,废话不多说,下面直接开始。


基础的 File API

File Api 提供了在浏览器中与本地文件进行交互的最基础的方法,不过值得注意的是,由于安全问题,开发者并不能主动的去访问客户端的文件信息,也就是说这一过程需要用户的参与,最常用的获取本地文件的手段莫过于两种:


  1. 用户通过 input[type = file] 控件选择了本地某个文件。

  2. 用于通过拖拽将本地的某一文件拖到浏览器完成上传。

通过上面两种形式,我们都可以获取到可以操作的 File 接口,不过还有一点值得注意的是,无论是通过利用控件的形式还是通过拖拽的形式,用户都可以同时选中多个文件,而当用户选择多个文件的时候我们获取到的其实是 FileList 接口,顾名思义,它就是一个 File 接口的集合。

那么,通过 File 接口我们能够获取到哪些信息呢?


  1. name: 文件名

  2. type: ASCII 编码,MIME 格式的文件类型。

  3. size: 文件所占的字节 ( byte )。

  4. lastModifiedDate: 文件最后修改的日期和时间。

注: File API 不能遍历文件目录。

通过上面介绍的这些内容,我们就可以很轻易的写出一个小 demo,就像下面的这样。

demo01.png

其实现过程就是利用 input[type=file] 控件选择多个文件,不过在这里我们并没有直接使用这个控件,而是利用 button 来触发这个控件的功能。然后通过用户选择的文件会返回一个 FileList 对象,通过对其包含的每个 File 进行属性的读取即可。其核心代码如下:

uploadButton.addEventListener("click", function() {
    fileInput.click();
}, false);

fileInput.addEventListener("change", function() {
    if (fileInput.files) {
        var length = fileInput.files.length;
        for(var i = 0; i < length; i++) {
            fileList.appendChild(getFileDetailDIV(fileInput.files[i]));
        }
    }
}, false);

这个时候这个小 demo 还不够人性化,毕竟有的人他就是不喜欢利用控件上传文件,他就是喜欢利用拖放将文件传上来,那么为了这部分用户,我们就得多费点脑筋了,怎么才能利用拖放获取到一个文件的信息呢?

在这之前,我想插入一些拖放的知识。因为网页中并不是每一种元素都可以成为放置目标,所以如果想自定义放置目标,那么我们需要修改 dragoverdragenter 的默认行为,代码如下:

var droptarget = document.getElementById("custom-target");

droptarget.addEventListener("dragenter", function(e) {
    e.preventDefault();
}, false);

droptarget.addEventListener("dragover", function(e) {
    e.preventDefault();
}, false);

还有一点值得注意的是,当你将目标拖拽到地点以后,鼠标松开的时候就会触发 drop 事件,不过放置事件也是有默认行为的,比如当拖拽的目标是图片的时候,页面就会转向图片,当拖拽的目标是音乐或者视屏的时候,页面就会按照默认的方式打开这些文件,所以如果不想这些事情发生,我们需要阻止 drop 事件的默认行为。

最后一点,当我们拖拽文件的时候,通过 dataTransfer,files 就可以获得选中的文件,而且其返回的结果是 FileList 接口。下面就让我们以拖拽的形式完成上面的功能。

demo02.png

其核心代码如下所示:

dragtarget.addEventListener("dragenter", function(e) {
    e.preventDefault();
}, false);

dragtarget.addEventListener("dragover", function(e) {
    e.preventDefault();
}, false);

dragtarget.addEventListener("drop", function(e) {
    e.preventDefault();

    var files = e.dataTransfer.files,
        length = files.length;

    for(var i = 0; i < length; i++) {
        fileList.appendChild(getFileDetailDIV(files[i]));
    }
}, false);

File Reader

上面已经介绍了 File API 的使用,不过仅仅是能够获取到文件的属性,实用价值非常有限,所以在 HTML5 File API 中提供了一个新的接口 FileReader,该接口为开发者提供了从客户端 JS 异步读取文件的方法,属性和事件,下面就先来看看它提供的四种不同的读取方法。


  1. readAsArrayBuffer( Blob ): 以 ArrayBuffer 格式返回文件内容。

  2. readAsBinaryString( Blob ): 以二进制字符串的形式返回文件内容。

  3. readAsText( Blob, [, encoding] ): 以 DOMString 文本返回文件内容。

  4. readAsDataURL( Blob ): 以数据 URL DOMString 返回文件内容。

事件如下:


  1. loadstart: 文件读取操作开始时触发。

  2. progress: 浏览器读取文件过程中触发。

  3. abort: 执行放弃操作时触发。

  4. error: 文件读取过程中出现错误时触发。

  5. load: 文件成功读取后触发。

  6. loadend 文件读取完成后(无论成功或者失败)触发。

既然已经知道了这么多的事件和方法,那么我们就的知道当读取完成后,我们需要的信息存放在何处?

通过上面的介绍,我们已经知道当文件读取成功后,会触发 load 事件,我们想要的事件就在 load 事件中的 event.target.result 中。下面我们针对各个方法做实验,首先创建一个文本 test.txt,其内容如下:

You can import usage data from your Google Analytics account and see exactly how well a feature is supported among your own site’s visitors. Look under the Settings panel to get started!

关于 readAsArrayBuffer()readAsBinaryString() 这两个方法在此就不演示了,因为我个人对 ArrayBuffer 的应用场景还不是很清楚,所以下面直接利用 readAsText()readAsDataURL() 这两个方法。

利用 readAsText() 的代码如下:

    var fileReader = new FileReader();
    fileReader.addEventListener("load", function(e) {
        console.log(e.target.result);
    }, false);
    fileReader.readAsDataURL(file);

其返回的结果如下所示:

demo03.png

可见,它只是将你选择的文本读取出来了,其实通过方法的名字你可能也已经猜出大概了。这有什么用呢?很明显,我们可以利用这个方法编写一个在线阅读或者修改的小应用。

还有一个方法是 readAsDataURL(), 这个方法的返回值如下:

demo04.png

可见,这个方法只是返回一个 URL 地址,而通过这个地址我们就可以获取到选中的文件,这个方法非常的有用,比如你想开发图片预览相关的功能或者是在线播放本地音频的应用,都可以利用该方法获取到一个连接到本地资源的 URL,然后进行操作。在以前,要完成同样的功能,必须要将相应的图片或者资源上传到服务器才可以使用。


好了,先写到这里,如果日后用到与文件操作相关的属性,还会更新本文章!

坚持原创技术分享,您的支持将鼓励我继续创作!