文档章节

html5对于文件的相关操作

marjey
 marjey
发布于 2016/11/13 09:49
字数 2057
阅读 22
收藏 0

今天在写前端的时候碰到一些问题,现在对于web网页操作文件进一步了解。

主要参照:http://www.cnblogs.com/zichi/p/html5-file-api.html

FileList 对象针对表单的 file 控件。当用户通过 file 控件选取文件后,这个控件的 files 属性值就是 FileList 对象。它在结构上类似于数组,包含用户选取的多个文件。如果 file 控件没有设置 multiple 属性,那么用户只能选择一个文件,FileList 对象也就只有一个元素了。

<input type='file' multiple/>
<script>
    document.querySelector('input').onchange = function () {
        console.log(this.files);
    };
</script>

控制台输出文件相关内容。

Blob

上图中我们看到,File 对象是继承自 Blob 对象的,Blob 又是什么鬼?

Blob(Binary Large Object)对象代表了一段二进制数据,提供了一系列操作接口。其他操作二进制数据的 API(比如 File 对象),都是建立在 Blob 对象基础上的,继承了它的属性和方法。

生成 Blob 对象有两种方法:一种是使用 Blob 构造函数,另一种是对现有的 Blob 对象使用 slice 方法切出一部分。

(1)Blob 构造函数,接受两个参数。第一个参数是一个包含实际数据的数组,第二个参数是数据的类型,这两个参数都不是必需的。

var a = ["hello", "world"];
var myBlob = new Blob(a, { "type" : "text/xml" });
console.log(myBlob);

(2)Blob 对象的 slice 方法,将二进制数据按照字节分块,返回一个新的 Blob 对象。

var a = ["hello", "world"];
var myBlob = new Blob(a, { "type" : "text/xml" });
var newBlob = myBlob.slice(0, 5);
console.log(newBlob);

Blob 对象有两个只读属性:

  • size:二进制数据的大小,单位为字节。(文件上传时可以在前端判断文件大小是否合适)
  • type:二进制数据的 MIME 类型,全部为小写,如果类型未知,则该值为空字符串。(文件上传时可以在前端判断文件类型是否合适)

FileReader

重头戏来了,FileReader API 才是我们接下去完成一些任务的关键。FileReader API 用于读取文件,即把文件内容读入内存。它的参数是 File 对象或 Blob 对象

对于不同类型的文件,FileReader 提供不同的方法读取文件。

  • readAsBinaryString(Blob|File):返回二进制字符串,该字符串每个字节包含一个 0 到 255 之间的整数。(已废弃)
  • readAsText(Blob|File, opt_encoding):返回文本字符串。默认情况下,文本编码格式是 UTF-8,可以通过可选的格式参数,指定其他编码格式的文本。
  • readAsDataURL(Blob|File):返回一个基于 Base64 编码的 data-uri 对象。
  • readAsArrayBuffer(Blob|File):返回一个 ArrayBuffer 对象。

除了以上四种不同的读取文件方法,FileReader API 还有一个 abort 方法,用于中止文件上传。

var reader = new FileReader();
reader.abort();

FileReader 对象采用异步方式读取文件,可以为一系列事件指定回调函数。

  • onabort 方法:读取中断或调用 reader.abort() 方法时触发。
  • onerror 方法:读取出错时触发。
  • onload 方法:读取成功后触发。
  • onloadend 方法:读取完成后触发,不管是否成功。触发顺序排在 onload 或 onerror 后面。
  • onloadstart 方法:读取将要开始时触发。
  • onprogress 方法:读取过程中周期性触发。(可以用来获取文件读取的进度)

以前在学习图片的 base64 编码的时候,写了一篇文章 获取图片 base64 编码的几种方法,当时还没有学习 File API,了解到 File API 也能做类似的事情,现在学到了,写了个简单的 demo http://hanzichi.github.io/2016/image2base64/,不仅能获取图片的 base64 编码,同时也能获取文字的 base64 编码,代码比较简单就不放了,可以 猛戳这里

获取到了文件的 base64 编码,做一些诸如图片预览的功能,也就手到擒来了,有兴趣的可以自己尝试下,类似的还有文字预览啊,等等。

URL

你以为 File API 就这样了吗?非也,还有个强大的东西没有介绍,URL 对象!

调用 URL 对象的 createObjectURL 方法,传入一个 File 对象或者 Blob 对象,能生成一个链接,听起来好像很吊的样子。

var objecturl =  window.URL.createObjectURL(blob);

上面的代码会对二进制数据生成一个 URL,这个 URL 可以放置于任何通常可以放置 URL 的地方,比如 img 标签的 src 属性。需要注意的是,即使是同样的二进制数据,每调用一次 URL.createObjectURL 方法,就会得到一个不一样的 URL。

这个 URL 的存在时间,等同于网页的存在时间,一旦网页刷新或卸载,这个 URL 就失效。(File 和 Blob 又何尝不是这样呢)除此之外,也可以手动调用 URL.revokeObjectURL 方法,使 URL 失效。

window.URL.revokeObjectURL(objectURL);

举个简单的例子。

var blob = new Blob(["Hello hanzichi"]);
var a = document.createElement("a");
a.href = window.URL.createObjectURL(blob);
a.download = "a.txt";
a.textContent = "Download";

document.body.appendChild(a);

页面上生成了一个超链接,点击它就能下载一个名为 a.txt 的文件,里面的内容是 Hello hanzichi

这里插点题外话,简单介绍下 H5 新增的 download 属性。对于一些诸如 exe,rar 等浏览器不能直接打开的文件类型,我们一般可以直接用一个 a 标签,将其指向文件在服务端的地址,点击即可下载。但是如果是一些浏览器能直接打开的文件,比如 txt,js 等,如果这样设置一个超链接,点击会直接打开文件,一般我们可以配合后端实现,比如用 PHP。

$file_name = "1.txt"; // 下载文件名
$file_dir = dirname(__FILE__). '/'; //下载文件存放目录
//输入文件标签
Header("Content-type: text/plain");
Header("Content-Disposition: attachment; filename=" . $file_name );

以上代码需要文件的 Content-type 属性值,安利一个网址,http://tool.oschina.net/commons ,各种文件类型的 Content-type 属性值一网打尽!

如果考虑到安全性,header + fread 可能会显得更严谨。

$file_name = "1.txt"; // 下载文件名
$file_dir = dirname(__FILE__). '/'; //下载文件存放目录

Header("Content-type: text/plain");
Header("Content-Disposition: attachment; filename=" . $file_name );
echo fread($file, filesize($file_dir . $file_name));

但是现在我们只需要在 a 标签上加上 download !

<a href="1.txt" download>download txt></a>

还可以给 download 加上属性值,即为下载的文件名。

<a href="1.txt" download="2.txt">download txt></a>

可以省略 .txt 的后缀名,浏览器会自行判断。

我们再回到 URL 上来。对于 File 或者 Blob 对象,我们可以这样理解,它们的存在,依赖于页面,而 URL 能给这些 "转瞬即逝" 的二进制对象一个临时的指向地址。

这个临时的地址还有什么用呢?也能做图片预览,相比前面用 readAsDataURL 的实现,更简单了。

<input type='file' multiple /><br/>
<img />
<script>
document.querySelector("input").onchange = function() {
  var files = this.files;
  document.querySelector("img").src = window.URL.createObjectURL(files[0]);
}
</script>

比如还有这样的需求,前端上传文件,要动态生成该文件的下载链接,也能用 URL 完成。

Canvas & dataURL & Blob

canvas 中有 toDataURL 函数,可以将 canvas 转为 dataURL 形式的 base64 编码,而 Blob 也可以转为 dataURL,这三者之间是否可以互相转换?有没有什么实用之处?

(1)canvas -> dataURL

用 toDataURL 方法,比较简单,不多说。

(2)blob -> dataURL

用 FileReader 的 readAsDataURL 方法,使用方式可以看 这个 demo

(3)dataURL -> blob

这个函数有点屌

function dataURLtoBlob(dataurl) {
  var arr = dataurl.split(','), mime = arr[0].match(/:(.*?);/)[1],
    bstr = atob(arr[1]), n = bstr.length, u8arr = new Uint8Array(n);
  while(n--){
    u8arr[n] = bstr.charCodeAt(n);
  }
  return new Blob([u8arr], {type:mime});
}

(4)dataURL - canvas

将 image 的 src 属性置为 dataURL,再用 drawImage 方法画上去。

(5)blob - canvas

如何把二进制形式的图片画上 canvas?先用 readAsDataURL 转为 dataURL,接着就是 (4) 的事情了。

(6)canvas - blob

canvas 转为 blob 也可以用 dataURL 做跳板,先将 canvas 转为 dataURL(1),再用 dataURL 转为 blob(3)。

利用它们之间的转换可以做些什么好玩的事呢?比如可以上传图片,对图片做各种处理,然后保存,看起来好像挺好玩的,等有空了搞个 demo 出来。

2016.11.11 add: canvas 有原生的 toBlob 方法,使得图片文件可以被缓存或保存到本地。

本文转载自:http://www.cnblogs.com/zichi/p/html5-file-api.html

marjey
粉丝 3
博文 173
码字总数 139219
作品 0
昆明
私信 提问
华丽丽的HTML5新特性

Web2.0带来的丰富互联网技术让所有人都享受到了技术发展和体验进步的乐趣。作为下一代互联网标准,HTML5自然也是备受期待和瞩目,技 术人员、设计者、互联网爱好者们都在热议HTML5究竟能带来...

小编辑
2011/07/13
1K
1
Flutter数据持久化入门以及与Web开发的对比

对于大部分安卓或者IOS开发人员来说,App的数据持久化可能是很平常的一个话题。但是对于Web开发人员来说,可能紧紧意味着localStorage和sessionStorage。 Web开发 localStorage和sessionStor...

阿尔卑斯de秘密
2018/11/23
0
0
HTML5的当下与未来?

HTML5技术而今已不再陌生,不管是趋之若鹜,热情拥抱,还是远远张望,保持距离,HTML5都是技术论坛热门的话题,给人的感觉就是酷、新、看上去很美 任何技术都有他的适用范围,HTML5技术是一种...

modernizr
2014/04/03
2.1K
2
HTML5(目前)无法帮你实现的五件事

一直以来,很多人都专注于HTML5能够实现什么(或者是如何将各种方法连接起来,实现一个更加优雅的解决方案)。而现在,也不少人想将目光投向那些HTML5无法实现的事情。MSDN上微软员工thebeeb...

虫虫
2011/12/12
3.9K
22
好程序员教程之HTML5中的storage 如何使用

HTML5中,我们常常用到storage,那这个storage到底是什么?有啥用呢?其实,storage是个很简单的东西,只要熟悉JavaScript中对象的童鞋,看完小编本文的分享,对storage的概念及用法应该都能...

好程序员IT
03/22
9
0

没有更多内容

加载失败,请刷新页面

加载更多

只需一步,在Spring Boot中统一Restful API返回值格式与统一处理异常

统一返回值 在前后端分离大行其道的今天,有一个统一的返回值格式不仅能使我们的接口看起来更漂亮,而且还可以使前端可以统一处理很多东西,避免很多问题的产生。 比较通用的返回值格式如下:...

晓月寒丶
昨天
59
0
区块链应用到供应链上的好处和实际案例

区块链可以解决供应链中的很多问题,例如记录以及追踪产品。那么使用区块链应用到各产品供应链上到底有什么好处?猎头悬赏平台解优人才网小编给大家做个简单的分享: 使用区块链的最突出的优...

猎头悬赏平台
昨天
28
0
全世界到底有多少软件开发人员?

埃文斯数据公司(Evans Data Corporation) 2019 最新的统计数据(原文)显示,2018 年全球共有 2300 万软件开发人员,预计到 2019 年底这个数字将达到 2640万,到 2023 年达到 2770万。 而来自...

红薯
昨天
65
0
Go 语言基础—— 通道(channel)

通过通信来共享内存(Java是通过共享内存来通信的) 定义 func service() string {time.Sleep(time.Millisecond * 50)return "Done"}func AsyncService() chan string {retCh := mak......

刘一草
昨天
58
0
Apache Flink 零基础入门(一):基础概念解析

Apache Flink 的定义、架构及原理 Apache Flink 是一个分布式大数据处理引擎,可对有限数据流和无限数据流进行有状态或无状态的计算,能够部署在各种集群环境,对各种规模大小的数据进行快速...

Vincent-Duan
昨天
60
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部