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,然后进行操作。在以前,要完成同样的功能,必须要将相应的图片或者资源上传到服务器才可以使用。


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

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 200,527评论 5 470
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 84,314评论 2 377
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 147,535评论 0 332
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,006评论 1 272
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 62,961评论 5 360
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,220评论 1 277
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,664评论 3 392
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,351评论 0 254
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,481评论 1 294
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,397评论 2 317
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,443评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,123评论 3 315
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,713评论 3 303
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,801评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,010评论 1 255
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,494评论 2 346
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,075评论 2 341

推荐阅读更多精彩内容

  • Android 自定义View的各种姿势1 Activity的显示之ViewRootImpl详解 Activity...
    passiontim阅读 171,285评论 25 707
  • 《裕语言》速成开发手册3.0 官方用户交流:iApp开发交流(1) 239547050iApp开发交流(2) 10...
    叶染柒丶阅读 25,660评论 5 18
  • Spring Cloud为开发人员提供了快速构建分布式系统中一些常见模式的工具(例如配置管理,服务发现,断路器,智...
    卡卡罗2017阅读 134,566评论 18 139
  • 一个优秀的人,无论走到哪里都会受人尊重,而一个快乐的人,走到哪里都会被人围绕。 这个人不一定优秀,可他足够...
    日复一日的梦想阅读 349评论 0 0
  • 那是最美好的时代,那是最糟糕的时代;那是智慧的年头,那是愚昧的年头;那是信仰的时期,那是怀疑的时期;那是光明的季节...
    三宅一生er阅读 238评论 0 0