本文来自《FileAPI 文件操作实战》
其他系列放在了Github,欢迎交流和Star

介绍

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();// 控制台输出结果应该是:helloreader.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);

后端相关

后端相关超出了本文的讨论范围,可以参考这篇文章。

兼容input 文件选择_「HTML5」FileAPI 文件操作实战相关推荐

  1. rfa 文件读取_「rfa」rfa文件用什么软件打开? - seo实验室

    rfa 后缀名.rfa的用什么软件可以打开?什么是文件扩展名为RFA?有没有人给您发送过RFA文件,而您却不知道该如何打开?可能您在电脑上发现了一个 RFA文件却不知道这是做什么用的?windows ...

  2. python 文件读写 newline_「Python」:文件读写

    原标题:「Python」:文件读写 ##############txt文件读写################## # txt文件:记事本文件,一般用来存储测试日志 # 方式1: 不推荐,每次读写结束 ...

  3. python读文件去除空行_「34」Python文件操作经典案例:CSV文件的读与写

    [1]认识CSV文件 CSV是Comma Separated Values的缩写,它是逗号分隔符文本格式,常用于数据交换.Excel文件和数据库数据的导入和导出. 鉴于CSV的应用场景,编程人员与它打 ...

  4. caffe模型文件解析_「机器学习」截取caffe模型中的某层

    通常情况下,训练好的caffe模型包含两个文件: prototxt:网络结构描述文件,存储了整个网络的图结构: caffemodel:权重文件,存储了模型权重的相关参数和具体信息 对于某些大型的网络, ...

  5. unity应用开发实战案例_「简历」STAR法则的实战应用,附手把手教学案例

    关注@应届生求职网,了解更多求职信息 本文共2072字,预计阅读需3分钟 本期分享导师-Anna_青云导师 51Job职场导师 知乎职场千赞答主 多年猎头及多行业人力资源管理经历 职业生涯规划师.职业 ...

  6. file 选择的文件胖多有多大_「HTML5 进阶」FileAPI 文件操作实战,内附详细案例,建议收藏...

    FileAPI 介绍 HTML5 为我们提供了 File API 相关规范.主要涉及 File 接口 和 FileReader 对象 . 本文整理了兼容性检测.文件选择.属性读取.文件读取.进度监控. ...

  7. python 文件路径_「按需学Python」 1. Glob库遍历路径/文件

    小前言: 本人Python小白,因为最近想整理下近10几年的老照片,然后就有了写脚本批处理的想法.初始需求其实很简单,就是筛选自己想要的照片到指定文件夹,然后按照exif信息重命名照片为拍摄时间_拍摄 ...

  8. 10你当前无权访问该文件夹_「文件保密小技巧」教你创建一个别人打不开也无法删除的文件夹...

    很多时候,我们电脑里面保存着一些比较隐私的文件,不想让别人看到或者不小心删除,怎么办?有很多办法,比如设置隐藏属性.设置密码等等.但小编要说,保密都是相对的,想要做到绝对保密很难,每种方法都有自己的漏 ...

  9. android r 编译找不到头文件_「投稿」iOS逆向——砸壳与反编译

    作者:疯狂的蛋神 近来对iOS逆向十分感兴趣,就在业余时间里自己在上网找了各种资料学习,发现许多资料对于一些细节描述的不够详细,所以也踩了很多坑,我也将自己踩的一些坑总结出来,希望对大家有所帮助. 注 ...

最新文章

  1. PCL点云配准(3)
  2. AngularJs $resource 高大上的数据交互
  3. GIS软件开发工具包TatukGIS Developer Kernel更新至v11.5,修复紧急问题
  4. 《无线网络安全攻防实战》读书笔记
  5. Python地信专题 | 基于geopandas的空间数据分析-坐标参考系篇
  6. 本次案例:对于sun 服务器的故障排查
  7. paradox 修改字段长度_400字的作文就只能写400字?刘强东:这不是笑话
  8. 一文带你熟悉Pytorch->Caffe->om模型转换流程
  9. 用 Java 拿下 HTML,分分钟写个小爬虫!
  10. 用户计算机安全管理,关于加强用户计算机安全管理工作的通知
  11. NPM酷库:chalk,多彩的粉笔
  12. linear regreesion 线性回归
  13. VTK-修改图片的像素
  14. 智能家居之红外遥控---手机万能红外遥控器
  15. C语言字符类型输入方式选择
  16. 修改Typora默认的字体为好看秀美的中文字体“华康手札体“
  17. java实现一个整数分解为两个质数乘积
  18. 基于JAVA星星电影购票网站计算机毕业设计源码+系统+数据库+lw文档+部署
  19. 7-13 查找奥运五环色的位置 (10分)
  20. Java中private方法可以被重写吗?

热门文章

  1. ASP.NET:判断session是否合法示例
  2. android google snake
  3. 洛谷 P2515 [HAOI2010]软件安装 解题报告
  4. go 排序sort的使用
  5. MariaDB Audit  Statistics
  6. 总结Cnblogs支持的常用Markdown语法
  7. 利用boost获取时间并格式化
  8. meta几个常用的地方
  9. ubuntu下安装ettercap
  10. 年终述职--常见问题分析解答