html5:FileAPI 文件操作实战

时间: 2019-07-22阅读: 1028标签: 文件

介绍

html5 为我们提供了 File API 相关规范。主要涉及 File 接口 和 FileReader 对象 。

本文整理了兼容性检测、文件选择、属性读取、文件读取、进度监控、大文件分片上传以及拖拽上传等开发中常见的前端文件操作。


准备工作

首先,我们的 File 来自于<input>标签中选中的文件列表。所以,准备如下的 html 代码

<input type="file" id="files" multiple />
<div id="list"></div>
<div id="images"></div>
<!-- File API相关操作写在了script.js中 -->
<script src="./script.js"></script>


检测兼容性

File 对象是特殊类型的 Blob。在 script 入口处,应该检测当前浏览器是否支持 File API:

if (!(window.File && window.FileReader && window.FileList && window.Blob)) {
  throw new Error("当前浏览器对FileAPI的支持不完善");
}


监听文件选择

对于 type 为 file 类型的<input>标签,在选择文件的时候,会触发change事件。用户选中的文件信息也会传入回调函数的第一个参数中。

function handleFileSelect(event) {
  const { files } = event.target;
  if (!files.length) {
    console.log("没有选择文件");
    return;
  }

  console.log("选中的文件信息是:", files);
}

document
  .querySelector("#files")
  .addEventListener("change", handleFileSelect, false);


文件属性-File

event.target.files 是一个FileList对象,它是一个由File对象组成的列表。

每个 File 对象,保存着选中的对应文件的属性。常用的用:

  • name:文件名
  • type:文件类型
  • size:文件大小

下面,通过 type 属性,过滤掉非图片类型的文件,只展示图片类型文件的信息:

function handleFileSelect(event) {
  const { files } = event.target;
  if (!files.length) {
    console.log("没有选择文件");
    return;
  }

  const innerhtml = [];
  const reImage = /image.*/;

  for (let file of files) {
    if (!reImage.test(file.type)) {
      continue;
    }

    innerhtml.push(
      `
      <li>
        <strong>${file.name}</strong>
        (${file.type || "n/a"}) -
        ${file.size} bytes
      </li>
      `
    );
  }

  document.querySelector("#list").innerhtml = `<ul>${innerhtml.join("")}</ul>`;
}


读取文件-FileReader

还是以图片读取为例,读取并且显示所有的图片类型文件。

文件读取需要使用FileReader对象,它常用 3 个回调方法:

  • onload: 文件读取完成
  • onloadstart:文件上传开始
  • onprogress : 文件上传中触发

和Image类似,在读取文件之前,需要先绑定事件处理。它读取操作有:readAsArrayBuffer、readAsDataURL、readAsBinaryString、readAsText。传入的参数就是File对象。

那么这几个方法有什么区别呢?不同的读取方式,回调事件onload接受到的event.target.result不相同。比如,readAsDataURL读取的话,result 是一个图片的 url。

下面就是读取图片文件,然后展示的一个例子:

function handleFileSelect(event) {
  let { files } = event.target;
  if (!files.length) {
    return;
  }

  let vm = document.createDocumentFragment(),
    re = /image.*/,
    loaded = 0, // 完成加载的图片数量
    total = 0; // 总共图片数量

  // 统计image文件数量
  for (let file of files) {
    re.test(file.type) && total++;
  }

  // onloadstart回调
  const handleLoadStart = (ev, file) =>
    console.log(`>>> Start load ${file.name}`);
  // onload回调
  const handleOnload = (ev, file) => {
    console.log(`<<< End load ${file.name}`);

    const img = document.createElement("img");
    img.height = 250;
    img.width = 250;
    img.src = ev.target.result;
    vm.appendChild(img);

    // 完成加载后,将其放入dom元素中
    if (++loaded === total) {
      document.querySelector("#images").appendChild(vm);
    }
  };

  for (let file of files) {
    if (!re.test(file.type)) {
      continue;
    }

    const reader = new FileReader();
    reader.onloadstart = ev => handleLoadStart(ev, file);
    reader.onload = ev => handleOnload(ev, file);
    // 读取文件对象
    reader.readAsDataURL(file);
  }
}

document
  .querySelector("#files")
  .addEventListener("change", handleFileSelect, false);


监控读取进度

在监控读取进度的时候,主要是处理 FileReader 对象上的 onprogress 事件。

下面的例子,请打开一个较大的文件来查看效果(否则一下就读取完了):

function handleFileSelect(event) {
  let { files } = event.target;
  if (!files.length) {
    return;
  }

  const handleLoadStart = (ev, file) =>
    console.log(`>>> Start load ${file.name}`);
  const handleProgress = (ev, file) => {
    if (!ev.lengthComputable) {
      return;
    }
    // 计算进度,并且以百分比形式展示
    const percent = Math.round((ev.loaded / ev.total) * 100);
    console.log(`<<< Loding ${file.name}, progress is ${percent}%`);
  };

  for (let file of files) {
    const reader = new FileReader();
    reader.onloadstart = ev => handleLoadStart(ev, file);
    reader.onprogress = ev => handleProgress(ev, file);
    reader.readAsArrayBuffer(file);
  }
}

document
  .querySelector("#files")
  .addEventListener("change", handleFileSelect, false);


大文件分片读取

在对于超大文件,一般采用分片上传的思路解决。文章开头有讲到,File 是 Blob 的一个特例。而 Blob 上有一个slice 方法,通过它,前端就可以实现分片读取大文件的操作。

为了方便说明,请先准备好一个 txt 文件,文件内容就是:hello world。

示例代码如下,代码中只读取前 5 个字节,由于每个英文字母占 1 个字节,所以打印结果应该是“hello”。

function handleFileSelect(event) {
  let { files } = event.target;
  if (!files.length) {
    return;
  }
  // 为了方便说明,这里仅仅读取第一个文件
  const file = files[0];
  // 读取前5个字节的内容
  const blob = file.slice(0, 5);

  const reader = new FileReader();
  // 控制台输出结果应该是:hello
  reader.onload = ev => console.log(ev.target.result);
  reader.readAsText(blob);
}

document
  .querySelector("#files")
  .addEventListener("change", handleFileSelect, false);


拖拽上传

和前面所述的 File API 相关是完全一样的。唯一需要特殊处理的是文件对象的获取入口改变了。对于<input>标签,监听 onchange 事件,FileList 存放在 event.target.files 中;对于拖拽操作,FileList 存放在拖拽事件的回调函数参数里,通过 event.dataTransfer.files 访问即可。

需要修改一下 html 代码

<!DOCTYPE html>
<head>
  <meta charset="UTF-8">
  <style>
    #container {
      width: 300px;
      height: 300px;
      border: 3px dotted red;
    }
  </style>
</head>
<body>
  <div id="container"></div>
  <script src="./script.js"></script>
</body>
</html>

脚本文件的代码如下:

function handleDropover(event) {
  event.stopPropagation();
  event.preventDefault();
}

function handleDrop(event) {
  event.stopPropagation();
  event.preventDefault();
  /***** 访问拖拽文件 *****/
  const files = event.dataTransfer.files;
  console.log(files);
  /**********/
}

const target = document.querySelector("#container");
target.addEventListener("dragover", handleDropover);
target.addEventListener("drop", handleDrop);


本文来自《FileAPI 文件操作实战》
其他所有系列都放在了Github


站长推荐

1.云服务推荐: 国内主流云服务商,各类云产品的最新活动,优惠券领取。地址:阿里云腾讯云华为云

2.广告联盟: 整理了目前主流的广告联盟平台,如果你有流量,可以作为参考选择适合你的平台点击进入

链接: http://www.fly63.com/article/detial/4308

php实现rar文件的读取和解压

PHP Rar Archiving 模块 (php_rar) 是一个读取和解压rar文件的模块,但不提供RAR压缩(打包)的功能。首先要到PECL的RAR页面下载DLL. 根据自己的情况选择下载对应版本的DLL.

js下载文件,判断文件是否返回

下载之前用的window.location.href下载的,但是这个判别不了文件是否返回,小文件倒还好,大的文件长时间没有下载也没有加载条什么的,用户有时会点击下载好几下,大的数据很容易将服务拖垮

angular2如何访问js文件

angular2访问js文件:先将要使用的js文件下载下来,放到angular2项目的src/assets/js目录,然后告诉angular去哪里加载该库并对要使用的对象进行声明,就可以直接访问js文件了。

什么是断点续传?前端如何实现文件的断点续传

什么是断点续传?就是下载文件时,不必重头开始下载,而是从指定的位置继续下载,这样的功能就叫做断点续传。前端通过FileList对象获取到相应的文件,按照指定的分割方式将大文件分段,然后一段一段地传给后端,后端再按顺序一段段将文件进行拼接。

源文件是什么?

在开发软件的过程中,我们需要将编写好的代码(Code)保存到一个文件中,这样代码才不会丢失,才能够被编译器找到,才能最终变成可执行文件。这种用来保存代码的文件就叫做源文件(Source File)。

HTML5中FileReader的使用

HTML5定义了FileReader作为文件API的重要成员用于读取文件,FileReader接口提供了读取文件的方法和包含读取结果的事件模型。 FileReader 的实例拥有 4 个方法,其中 3 个用以读取文件,另一个用来中断读取。

lock文件_我们为什么需要 lock 文件

从 Yarn 横空出世推出 lock 文件以来,已经两年多时间了,npm 也在 5.0 版本加入了类似的功能,lock 文件越来越被开发者们接收和认可。本篇文章想从前端视角探讨一下我们为什么需要 lock 文件,以及它的一些成本与风险,当然其中一些观点对于后端也是适用的

TypeScript声明文件

当使用第三方库时,我们需要引用它的声明文件,才能获得对应的代码补全、接口提示等功能。假如我们想使用第三方库 jQuery,一种常见的方式是在 html 中通过 <script> 标签引入 jQuery

JavaScript 如何读取本地文件

出于安全和隐私的原因,web应用程序不能直接访问用户设备上的文件。如果需要读取一个或多个本地文件,可以通过使用input file和FileReader来实现。在这篇文章中,我们将通过一些例子来看看它是如何工作的。

使用HTML5来实现本地文件读取和写入

最近有这样一个需求,就是在HTML页面中有个按钮导出,点击它,将构造一个文档并存储到本地文件系统中。另外还有个按钮,点击它,从本地文件系统中读取一个文件并对内容进行分析。

点击更多...

内容以共享、参考、研究为目的,不存在任何商业目的。其版权属原作者所有,如有侵权或违规,请与小编联系!情况属实本人将予以删除!

文章投稿关于web前端网站点搜索站长推荐网站地图站长QQ:522607023

小程序专栏: 土味情话心理测试脑筋急转弯幽默笑话段子句子语录成语大全运营推广