您当前的位置:首页 > 电脑百科 > 程序开发 > 语言 > HTML

「HTML5 进阶」FileAPI 文件操作实战,内附详细案例,建议收藏

时间:2019-07-23 09:32:35  来源:  作者:
「HTML5 进阶」FileAPI 文件操作实战,内附详细案例,建议收藏

FileAPI

介绍

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>`;
}
「HTML5 进阶」FileAPI 文件操作实战,内附详细案例,建议收藏

FileReader

读取文件-FileReader

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

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

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

和Image类似,在读取文件之前,需要先绑定事件处理。它读取操作有:readAsArrayBufferreadAsDataURLreadAsBinaryStringreadAsText。传入的参数就是 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);
「HTML5 进阶」FileAPI 文件操作实战,内附详细案例,建议收藏

slice

大文件分片读取

在对于超大文件,一般采用分片上传的思路解决。文章开头有讲到,File 是 Blob 的一个特例。而 Blob 上有一个 slice (https://developer.mozilla.org/zh-CN/docs/Web/API/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);

后端相关

后端相关超出了本文的讨论范围,可以参考这篇文章(https://github.com/purplebamboo/blog/issues/17)。

版权

作者:心谭

链接:https://juejin.im/post/5d35af63e51d454fa33b199e

著作权归作者所有。



Tags:FileAPI   点击:()  评论:()
声明:本站部分内容及图片来自互联网,转载是出于传递更多信息之目的,内容观点仅代表作者本人,如有任何标注错误或版权侵犯请与我们联系(Email:2595517585@qq.com),我们将及时更正、删除,谢谢。
▌相关推荐
FileAPI介绍HTML5 为我们提供了 File API 相关规范。主要涉及 File 接口 和 FileReader 对象 。本文整理了兼容性检测、文件选择、属性读取、文件读取、进度监控、大文件分...【详细内容】
2019-07-23  Tags: FileAPI  点击:(363)  评论:(0)  加入收藏
▌简易百科推荐
此文由掘金@天行天忌授权发布,前端晚间课对其内容进行微改。 HTML,超文本标记语言,是一种用于创建网页的标准标记语言。自从引入 HTML 以来,它就一直用于构建互联网。与 JavaScr...【详细内容】
2021-11-23  前端晚间课    Tags:HTML6   点击:(326)  评论:(0)  加入收藏
HTML是什么?超文本标记语言(Hyper Text Markup Language),标准通用标记语言下的一个应用。HTML 不是一种编程语言,而是一种标记语言 (markup language),是网页制作所必备的。“...【详细内容】
2021-11-05  人生三部曲丶    Tags:HTML   点击:(40)  评论:(0)  加入收藏
一、iframe标签 自己编写的页面中如果要引用外部的页面的话,可以使用iframe标签来实现。为了更好地理解举个例子,前面几篇中我们都是在index.hmtl中编写代码。如果有个需求是...【详细内容】
2021-11-03  HillelDu    Tags:html   点击:(29)  评论:(0)  加入收藏
我们倾向于使用HTML与CSS、JavaScript等,使我们的网站或博客看起来更有吸引力,但你知道仅HTML就有很多实用的秘密,可能会派上用场,帮助你设计一个华丽的网站?下面是一些很酷的HTM...【详细内容】
2021-08-13  杭州程序员小张    Tags:HTML   点击:(90)  评论:(0)  加入收藏
meta 标签分两大部分:HTTP 标题信息(http-equiv)和页面描述信息(name)。 1、声明文档使用的字符编码<meta charset=&#39;utf-8&#39;>以下设置更为详细:<meta http-equiv="Content-...【详细内容】
2021-08-12  简易编程    Tags:meta标签   点击:(91)  评论:(0)  加入收藏
本节我们讲HTML表单标签,当你在网页输入框提交一个数据,这条数据一般是提交给了服务器,然后服务器根据请求返回你想要的数据,这个你输入信息的输入框或者提交的按钮就是HTML表...【详细内容】
2021-06-25  科技现象    Tags:HTML   点击:(141)  评论:(0)  加入收藏
背景日常工作中,项目编程免不了需要使用配置文件,早期yaml出现之前,大部分配置文件采用xml形式,但是以xml格式储存的数据要比以其他格式(如json、yaml)储存占有的空间要大得多,因为...【详细内容】
2021-06-21  爱读书的程序员    Tags:yaml   点击:(265)  评论:(0)  加入收藏
XML; 是什么? Extensible Markup Languare 可扩展标记型语言 为什么要有XML? 1.HTML的标签是固定的,不可以改变,也不可以进行一个&middot;&middot;&middot;扩展 2.HTML语法松散...【详细内容】
2021-06-01  LeviT    Tags:XML   点击:(193)  评论:(0)  加入收藏
同事跟我说他用jQuery取不到页面上隐藏元素input的值,他的html页面大概内容如下。<!DOCTYPE html><html lang="zh"> <head> <meta http-equiv="Content-Type" content="text/...【详细内容】
2021-05-18  IT洞察者    Tags:Html   点击:(220)  评论:(0)  加入收藏
HTML5语义化与新特性什么是HTML语义化?表示选择合适的标签(语义化标签)便于开发者阅读和写出更优雅的代码为什么要使用语义化标签?1). 在没有CSS样式的情况下,页面整体也会呈现...【详细内容】
2021-03-02      Tags:HTML   点击:(236)  评论:(0)  加入收藏
相关文章
    无相关信息
最新更新
栏目热门
栏目头条