欢迎各位兄弟 发布技术文章
这里的技术是共享的
在过去,浏览器是不允许我们读取本地的文件,包括图片。因此,当我们需要预览一个图片的时候,往往先将它传送到服务端,然后服务端返回一个访问url地址,达到预览图片的功能。而如今,随着标准不断的改善,javascript里的API越来越多,我们可以通过直接读取本地文件的方式,加载我们想要看到的文本或者图片,一定程度上减少了服务端的压力。
接下来我们说一下运行环境和使用的库:
1. chrome 浏览器
2. zepto.js
其实在之前,我们有介绍过javascript里的 File 对象,它只能通过 input[type=file]元素获取。当用户触发了文件控件的onclick事件,同时选择了某一个文件确认时,触发文件控件的onchange事件。
一 : 案例页面结构
<body>
<article>
<header id="header"><h1>文件上传</h1></header>
<section class="box">
<form id="form" enctype='multipart/form-data' method='post' action='#'>
<div class="upload-label"><h2>请选择文件</h2></div>
<div class="upload-box add-button"></div>
<button class="upload-button" type="submit">上传</button>
<input type="file" name="files" id="files" >
</form>
</section>
</article>
</body>
主要关注的一点是<input type="file" name="files" id="files" > 我们这个form表单中存在这一个input[type=file]的元素,只有通过这一个接口,我们才可已调用电脑的文件管理器资源。因此很多时候我们会重写打开文件的界面,因为原生的界面的确不符合我们的审美。
下面是一张我写的一个简单的界面,相比之前有了很好的改善。
这是在手机上的一个显示,在这里我们就不纠结css样式了。直接看重点吧。
二: 通过zepto库绑定dom元素的事件
$(function(){
var maxlen = 5, //文件可读取最大长度
filelist = [], //存放 File对象数组
index = 0; //当前存放File的长度
// 按钮元素监听click事件,执行add方法
$(".add-button").bind('click',add);
// input[type=file]元素监听change事件 执行filter方法
$("#files").bind('change',filter);
// 模拟input[type=file]添加文件的动作
function add(e){
if (index < maxlen ){
$("#files").trigger("click");
}else{
// 超过了选中文件文件的限制
// AnimateUtils.info('超过最大上传限制');
}
}
// 过滤文件类型
function filter(e){
var files = e.target.files, // 获取本地文件File对象集合
typelist = ["image/jpeg","image/png"], // 合法文件type列表
filetype, // 当前文件的类型
isPic; // 文件类型是否合法标识
// 针对PC端多选的情况,前提是 input[type=file]元素包含 multiple属性
for (var i =0,len=files.length; i <len && index < 5 ;i++){
filetype = files[i].type;
//判断filetype是否属于图片
isPic= typelist.some(function(item){return item == filetype;});
if(isPic){
filelist.push(files[i]); //添加至文件列表
addImage(files[i]); //同时添加到页面
index++;
}else{
// 提示文件非图片
// AnimateUtils.info('不支持的文件类型');
}
}
}
});
这里可能写的比较乱,我们来好好梳理一下,首先当用户点击了<div class="upload-box add-button"></div>元素时,它会trigger(触发 ) <input type="file" name="files" id="files" > 的click事件。这么一来,就好像是点击了”文件控件”的按钮一样。
三:重点 : 理解File类型
我们是如何获取到File类型的实例的呢 ? 答案就是在 <input type="file" name="files" id="files" > 这个元素里。一旦你绑定了它的onchange事件,它会将你选中的文件进行封装成一个File类型的实例。存放在目标元素的files引用中,接下来我们可以来看看这个对象实例到底是怎么样的。
原来files引用的是一个FileList集合,里面存放了File类型的数据, 每一个File类型都包含以下5个主要的参数。
lastModified #保存的是一个时间戳,表示文件最后修改的时间
lastModifiedDate #保存的是一个Date类型,是时间戳翻译的格式
name #保存的是我们选择的文件的名称
size #文件的大小 单位是字节
type #文件的类型 如果没有特定的类型,比如说文本文件,一般为空字符串
其实我们截图中,还可以发现File类型是继承Blob类型的,因此文件可以通过文本的方式进行读取。在我们上面的代码中,其实有一个addImage方法并没有介绍,其实它主要就是将这个指向本地文件的引用对象通过某种方式读取到浏览器中。这种方式就是借用了第二要说的类型,FileReader类型。
四 : 介绍FileReader类型
我们都知道一个文件要是很大的话,直接读取会导致操作阻塞,必须得要等文件读取完后才可以进行其他操作。而FileReader类型实现的就是异步文件读取机制。书上说,可以把它当做XMLHttpRequest对象,区别在于它面向的是本地文件系统,而XMLHttpRequest是面向远程服务器。
接下来我们来继续完善上面的例子,把FileReader类型的对象实例创建出来,然后对File类型的实例操作。
// 将图片加载至浏览器中,并且显示出来
function addImage(file){
// 创建 一个FileReader对象
var reader = new FileReader();
// 读取文件作为URL可访问地址
reader.readAsDataURL(file);
// 监控读取加载过程
reader.onprogress =function(e){
// 是否支持获取当前读取文件长度
if(e.lengthComputable){
// 将新创建的一个展示区域元素存放在 reader.uploadBox 中
reader.uploadBox= reader.uploadBox || $('<div class="upload-box"></div>').insertBefore('.add-button');
// 读取进度显示
reader.uploadBox.text( Math.ceil((e.loaded / e.total) * 100) +"%");
}
//异步加载文件成功
reader.onload = function(e){
// this 对象为reader
// reader.result 表示图片地址
reader.uploadBox.wrapInner('<img style="width:100%;height:100%; padding:.2rem;" src="'+reader.result+'" alt="'+file.name+'" />');
}
}
这里发现我们只是使用了FileReader类型里的 readAsDataURL方法,还有onprogress事件和onload事件。很明显,想要学习FileReader类型,这个例子还是不够的。接下来我们来看看FileReader类型可以使用的方法和监听事件。
可用方法:
1. readAsText(file,encoding) 将以纯文本的形式读取文件,可以指定编码类型,结果保存在result属性中。
2. readAsDataURL(file) 读取文件并将文件以数据URI的方式保存在result属性中。
3. readAsBinaryString(file) 读取文件并将一个字符串保存在result属性中,其中一个字符表示一个字节。
4. readAsArrayBuffer(file) 读取文件并将一个包含文件内容的ArrayBuffer保存在result属性中。
可用事件:
error事件
读取失败后触发, 失败的原因可能为 未找到文件,安全性错误,读取中断,文件不可读,编码错误.错误都会以数字的形式存放在code属性中。
progress事件
正在读取中触发,每50ms触发一次 其中event对象会包含 lengthComputable , loaded , total 属性。分别表示是否可以计算长度,当前加载长度和总共需要加载长度。
load事件 读取完毕后触发
error事件和load事件是不可以同时触发的,因为完成与完成失败是完全对立的结果。
我们来看一下加载图片成功后显示的页面吧
————————————————
版权声明:本文为CSDN博主「子祥」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:
https://blog.csdn.net/lizixiang1993/article/details/45197171