HTML5 之 FileReader 的使用 (二) (网页上图片拖拽并且预显示可在这里学到) [转载]
转载至 : http://www.360doc.com/content/14/0214/18/1457948_352511645.shtml
FileReader 资料(英文): https://developer.mozilla.org/en-US/docs/Web/API/FileReader#State_constants
前面本博介绍了File API,这里将继续介绍一下FileReader,用FileReader具体地读取文件内容。
一、FileReader读取文件内容
File API一文中主要介绍获取文件句柄的方法,接下来我们就要利用该文件句柄来读取文件内容,这是通过FileReader来实现的,通过FileReader接口,我们可以异步地将文件内容加载到内存中,赋予某个js变量。
FileReader具体支持哪些方法和事件,这里就不介绍了,有兴趣的可以去w3c官网上看看FileReader介绍,这里主要介绍一下FileReader两个常见应用。
1、预览本地图片
这里主要用到FileReader的readAsDataURL方法,通过将图片数据读取成Data URL的方法,将图片展示出来,关于DATA URI。
示例脚本:
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
|
function fileSelect(e) { e = e || window.event; var files = e.target.files; //FileList Objects var ireg = /image\/.*/i, p = document.getElementById('Preview'); var ul = document.getElementById('Errors'); for(var i = 0, f; f = files[i]; i++) { if(!f.type.match(ireg)) { //设置错误信息 var li = document.createElement('li'); li.innerHTML = '<li>' + f.name +'不是图片文件.</li>'; ul.appendChild(li); continue; } var reader = new FileReader(); reader.onload = (function(file) { return function(e) { var span = document.createElement('span'); span.innerHTML = '<img class="thumb" src="'+this.result +'" alt="'+ file.name +'" />'; p.insertBefore(span, null); }; })(f); //读取文件内容 reader.readAsDataURL(f); }} if(window.File && window.FileList && window.FileReader && window.Blob) { document.getElementById('Files').addEventListener('change', fileSelect, false);} else { document.write('您的浏览器不支持File Api');} |
由以上代码可知,调用FileReader的readAsDataURL接口,将启动异步加载文件内容,通过给reader监听一个onload事件,将数据加载完毕后,在onload事件处理中,通过reader的result属性即可获得文件内容,查看示例>>。
NOTE:在示例中,我给图片指定了一个height:75px的css样式,主要是为了让浏览器对图片进行等比缩放处理,所以在浏览器中展示出来的图片并不是原始大小的图片,而是经过浏览器自动等比缩放的图片;如果需要查看原始尺寸图片,可点击相应图片;再次单击该图片,则恢复小图片。
2、预览文本文件
这里主要用到FileReader的readAsText,对于诸如mimetype为text/plain、text/html等文件均认为是文本文件,即minetype为text开头都能在本例中预览。
NOTE:由于需要在页面上预览文本,如果使用innerHTML插入文本的话,则需要对html中一些特殊字符进行实体编码,这样才能保证正常显示文本。
简易的encodeHTML方法:
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
|
function encodeHTML(source) { return source .replace(/&/g, '&') .replace(/</g, '<') .replace(/>/g, '>') .replace(/"/, '"') .replace(/'/, ''');};function fileSelect(e) { e = e || window.event; var files = e.target.files; //FileList Objects var ireg = /text\/.*/i, p = document.getElementById('Preview'); var ul = document.getElementById('Errors'); for(var i = 0, f; f = files[i]; i++) { console.log(f.type); if(!f.type.match(ireg)) { //设置错误信息 var li = document.createElement('li'); li.innerHTML = '<li>' + f.name +'不是文本文件.</li>'; ul.appendChild(li); continue; } var reader = new FileReader(); reader.onload = (function(file) { return function(e) { var div = document.createElement('div'); div.className = "text" div.innerHTML = encodeHTML(this.result); p.insertBefore(div, null); }; })(f); //读取文件内容 reader.readAsText(f); }} if(window.File && window.FileList && window.FileReader && window.Blob) { document.getElementById('Files').addEventListener('change', fileSelect, false);} else { document.write('您的浏览器不支持File Api');} |
二、分段读取文件内容(slice)
有的时候,一次性将一个大文件读入内存,并不是一个很好的选择(如果文件太大,使用FileReader读取文件内容,可能直接导致浏览器崩溃),w3c也想到了这种情况,所以html5允许对文件进行分段读取。
chrome以及firefox已经将File slice api调整为如下:
|
1
2
3
4
5
6
7
|
var blob;if(file.webkitSlice) { //Blob中的方法 blob = file.webkitSlice(start, end + 1,'text/plain;charset=UTF-8');} else if(file.mozSlice) { blob = file.mozSlice(start, end + 1, 'text/plain;charset=UTF-8');} |
本例使用了FileReader的onloadend事件来检测读取成功与否,如果用onloadend则必须检测一下FileReader readyState,因为read abort时也会触发onloadend事件,如果我们采用onload,则可以不用检测readyState。
示例代码:
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
|
function readBlob(start, end) { var files = document.getElementById('file').files; if(!files.length) { alert('请选择文件'); return false; } var file = files[0], start = parseInt(start, 10) || 0, end = parseInt(end, 10) || (file.size - 1); var r = document.getElementById('range'), c = document.getElementById('content'); var reader = new FileReader(); reader.onloadend = function(e) { if(this.readyState == FileReader.DONE) { c.textContent = this.result; r.textContent = "Read bytes: " + (start + 1) + " - "+ (end + 1) + " of " + file.size + " bytes"; } }; var blob; if(file.webkitSlice) { //Blob中的方法 blob = file.webkitSlice(start, end + 1,'text/plain;charset=UTF-8'); } else if(file.mozSlice) { blob = file.mozSlice(start, end + 1,'text/plain;charset=UTF-8'); } reader.readAsBinaryString(blob);};try { document.getElementById('buttons').addEventListener('click',function(e) { if(e.target.tagName.toLowerCase() == 'button') { var start = e.target.getAttribute('data-start'), end = e.target.getAttribute('data-end'); readBlob(start, end); } });} catch(ex) { alert('something error happens!')} |
NOTE:readAsBinaryString这个方法,读取的二进制字符串,在页面显示,出现中文乱码,不知道怎么解决,如果用reader.readAsText即可正常显示中文;在w3c官网上:binary string, in which every byte is represented by an integer in the range [0..255],而中文却不在[0...255]内,难道是因为这样才出现乱码?
三、FileReader进度条
既然FileReader是异步读取文件内容,那么就应该可以监听它的读取进度。事实上,FileReader的onloadstart以及onprogress等事件,可以用来监听FileReader的读取进度。
在onprogress的事件处理器中,提供了一个ProgressEvent对象,这个事件对象实际上继承了Event对象,提供了三个只读属性:lengthComputable、loaded、total;通过以上几个属性,即可实时显示读取进度。w3c官网上对它的定义如下:
|
1
2
3
4
5
|
interface ProgressEvent : Event { readonly attribute boolean lengthComputable; readonly attribute unsigned long long loaded; readonly attribute unsigned long long total;}; |
如果处理的文件太大,可能会导致浏览器崩溃(chrome下一般都会崩溃掉,而firefox则不会,不过会触发FileReader的onerror事件,文件读取失败),所以为了安全地、正常地观察到文件读取进度,我们采用分段读取的方法来测试FileReader的进度条。
HTML代码如下:
|
1
2
3
4
5
6
7
8
9
10
11
|
<form> <fieldset> <legend>分度读取文件:</legend> <input type="file" id="File" /> <input type="button" value="中断" id="Abort" /> <p> <label>读取进度:</label><progress id="Progress"value="0" max="100"></progress> </p> <p id="Status"></p> </fieldset></form> |
JS代码如下:
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
|
var h = { init: function() { var me = this; document.getElementById('File').onchange = me.fileHandler; document.getElementById('Abort').onclick = me.abortHandler; me.status = document.getElementById('Status'); me.progress = document.getElementById('Progress'); me.percent = document.getElementById('Percent'); me.loaded = 0; //每次读取1M me.step = 1024 * 1024; me.times = 0; }, fileHandler: function(e) { var me = h; var file = me.file = this.files[0]; var reader = me.reader = new FileReader(); // me.total = file.size; reader.onloadstart = me.onLoadStart; reader.onprogress = me.onProgress; reader.onabort = me.onAbort; reader.onerror = me.onerror; reader.onload = me.onLoad; reader.onloadend = me.onLoadEnd; //读取第一块 me.readBlob(file, 0); }, onLoadStart: function() { var me = h; }, onProgress: function(e) { var me = h; me.loaded += e.loaded; //更新进度条 me.progress.value = (me.loaded / me.total) * 100; }, onAbort: function() { var me = h; }, onError: function() { var me = h; }, onLoad: function() { var me = h; if(me.loaded < me.total) { me.readBlob(me.loaded); } else { me.loaded = me.total; } }, onLoadEnd: function() { var me = h; }, readBlob: function(start) { var me = h; var blob, file = me.file; me.times += 1; if(file.webkitSlice) { blob = file.webkitSlice(start, start + me.step + 1); } else if(file.mozSlice) { blob = file.mozSlice(start, start + me.step + 1); } me.reader.readAsText(blob); }, abortHandler: function() { var me = h; if(me.reader) { me.reader.abort(); } }};h.init(); |
例子中的进度条采用html5 progress元素来实现的。
每次读取1M的字节(你也可以随便改步长,比如说一次一个字节,然后传一个大小为几字节的文件,也能很好地观察到进度),在一次读取完毕后,onload事件中开启下一次读取,直至整个文件都读取完毕。
如果您的浏览器支持html5,您可以试一下:
读取进度:
这个示例中,没有限制文件大小,读取大文件时,也不会出现浏览器崩溃的情况,可以正常观察到文件的读取进度。
四、参考文章
1、File API3、Blob
HTML5 之 FileReader 的使用 (二) (网页上图片拖拽并且预显示可在这里学到) [转载]的更多相关文章
- HTML5 之 FileReader 的使用 (网页上图片拖拽并且预显示可在这里学到) [转载]
转载至 : http://www.360doc.com/content/14/0214/18/1457948_352511416.shtml FileReader 资料(英文) : https://d ...
- FileReader (三) - 网页拖拽并预显示图片简单实现
以下是一个很贱很简单的一个 在网页上图拽图片并预显示的demo. 我是从https://developer.mozilla.org/en-US/docs/Web/API/FileReader#Stat ...
- HTML5多图片拖拽上传带进度条
前言 昨天利用css2的clip属性实现了网页进度条觉得还不错,但是很多情况下,我们在那些时候用进度条呢,一般网页加载的时候如果有需要可以用,那么问题就来了,怎么才算整个加载完毕呢,是页面主要模块加载 ...
- HTML5图片拖拽预览原理及实现
一.前言 这两天恰好有一位同事问我怎样做一个图片预览功能.作为现代人的我们首先想到的当然是HTML5啦,其实HTML5做图片预览已经是一个老生常谈的问题了.我在这里就简单说说其中相关的一些东西,当然会 ...
- canvas 图片拖拽旋转之二——canvas状态保存(save和restore)
引言 在上一篇日志“canvas 图片拖拽旋转之一”中,对坐标转换有了比较深入的了解,但是仅仅利用坐标转换实现的拖拽旋转,会改变canvas坐标系的状态,从而影响画布上其他元素的绘制.因此,这个时候需 ...
- javascript小实例,PC网页里的拖拽
几年前,我参与设计开发一个房产网的项目,我负责前端工作,由于项目经理要求比较高,参考了很多房产类网站比较优秀的功能,想把别人比较优秀的设计和想法集合到一起,那时的设计稿和功能实现,简直就是改了又改,今 ...
- .net core版 文件上传/ 支持批量上传,拖拽以及预览,bootstrap fileinput上传文件
asp.net mvc请移步 mvc文件上传支持批量上传,拖拽以及预览,文件内容校验 本篇内容主要解决.net core中文件上传的问题 开发环境:ubuntu+vscode 1.导入所需要的包:n ...
- 通过 JS 实现简单的拖拽功能并且可以在特定元素上禁止拖拽
前言 关于讲解 JS 的拖拽功能的文章数不胜数,我确实没有必要大费周章再写一篇重复的文章来吸引眼球.本文的重点是讲解如何在某些特定的元素上禁止拖拽.这是我在编写插件时遇到的问题,其实很多插件的拖拽功能 ...
- HTML5——将图片拖拽上传
如下图所示: 代码如下: <!DOCTYPE html> <html> <head> <meta charset="utf-8"> ...
随机推荐
- cf20B Equation(认真仔细题)
题意: 求AX^2+BX+C=0的根 思路: 考虑到A,B,C所有可能的情况 代码: double a,b,c; int main(){ cin>>a>>b>>c; ...
- 我为啥开始用CSDN博客
今晚开通CSDN博客,并且决定以后每天都使用这个不错的东西.与此同时,在博客园也开通了一个:http://www.cnblogs.com/fish7/ 我原本是把做过的题都用WPS整理的,然后每次打印 ...
- 使用.NET6打造动态API
ApiLite是直接将Service层自动生成api路由,可以不用添加Controller,支持模块插件化,在项目开发中能够提高工作效率,降低代码量. 开发环境 .NET SDK 6.0.100-rc ...
- 【网络好文】---MySQL为Null导致的四大坑
正式开始之前,我们先来看下 MySQL 服务器的配置和版本号信息,如所示: select version(); -- 版本为 8.0.22 "兵马未动粮草先行",看完了相关的配置之 ...
- github上传和删除文件(三)
上传文件: git init git add * git commit -m "description" //git remote rm origin 或查看当前 git remo ...
- virtualbox + vagrant 安装centos7 以及 vagrant up下载太慢的解决方案
下载安装 virtualbox下载 vagrant下载 下载启动镜像vagrant up有下载过慢的问题,可以到网页vagrant镜像仓库,找到自己需要的镜像,选择virtualbox版本下载 下载好 ...
- 关于 RocketMQ 事务消息的正确打开方式 → 你学废了吗
开心一刻 昨晚和一哥们一起吃夜宵,点了几瓶啤酒 不一会天空下起了小雨,哥们突然道:糟了 我:怎么了 哥们:外面下雨了,我老婆还在等着我去接她 他给了自己一巴掌,说道:真他妈不是个东西 我心想:哥们真是 ...
- C# 获取PDF中的数字签名证书
PDF中的加数字签名是对文档权威性的有效证明.我们在向PDF文档添加签名时,需要准备可信任的签名证书.同时,对已有的签名,可验证签名是否有效,也可以获取文档中的签名证书信息.下面,以C#代码示例展示如 ...
- requests之代理的使用
import requests # 访问url url = 'http://www.baidu.com/s?' # 请求头 headers = { 'User-Agent': 'Mozilla/5.0 ...
- 网络带宽和速度测试windows和linux用iperf工具
网络带宽和速度测试windows和linux用iperf工具 Iperf是一个网络性能测试工具.Iperf可以测试TCP和UDP带宽质量.Iperf可以测量最大TCP带宽,具有多种参数和UDP特性 ...