以前在项目中做用户头像上传预览功能,一般都是把本地图片先上传到服务器,然后把服务器返回的图像URL直接赋值给页面<img>元素的src属性,实现预览效果。不过如今HTML5大行其道,新兴的API如FileReader可以直接在本地读取文件属性,在不用跟服务器打交道的情况直接在本地实现图片上传预览功能。
一、File API
HTML5在DOM中为<input type="file">元素添加了一个files集合,在上传一个或者多个文件时,files集合就包含一组File对象,每个File对象对应着选择上传的文件。
File对象具有三个常用属性:
- name:文件名
- size:文件的字节大小
- type:文件的MIME类型
<input type="file" multiple id="myFile">
<script>
var inp = document.getElementById('myFile');
inp.addEventListener('change',function() {
console.log(this.files);
});
</script>
如上述代码,上传三张图片,在控制台打印结果如下:
其中每一个File对象又如下:
二、FileReader
File API 提供了一个FileReader对象,它是一种异步文件读取机制,可以直接读取文件中的数据。
FileReader常用读取数据方法:
- readAsText(file):以文本形式读取文件,读取到的文本保存在FileReader的result属性中。
- readAsDataURL(file):读取文件以数据URI的形式保存在result属性中。
FileReader读取文件为异步的,就像XHR一样,也提供一些钩子方法,如:
- progress:进度事件,提供如XHR一样的信息属性(lengthComputable、loaded、total)
- load:读取完毕事件
- error:错误事件
<input type="file" multiple id="myFile">
<div id="progress"></div>
<div id="complete"></div>
<script>
var inp = document.getElementById('myFile');
var progressDiv = document.getElementById('progress');
var completeDiv = document.getElementById('complete');
inp.addEventListener('change',function() {
// 获取上传的文件对象
var file = this.files[0];
// 实例化一个FileReader对象
var reader = new FileReader();
// 上传的文件是一个图片,将其读取为数据URI形式保存在result属性中
reader.readAsDataURL(file);
// 进度事件
reader.onprogress = function(e) {
if(e.lengthComputable) {
progressDiv.innerHTML = e.loaded + ':' + e.total; // 已加载数据大小:数据总大小
}
}
// 读取完毕
reader.onload = function(e) {
// 将保存在result属性中的URI直接赋值给img的src属性
var img = '<img src="' + reader.result + '">';
completeDiv.innerHTML = img;
}
});
</script>
以上代码就实现了本地图片上传预览功能:
三、对象URL
利用FileReader可以很方便的读取文本文件或者图像文件并将它保存在其result属性中,以便后续使用,如果已知上传文件就为图片,只要获取到它的URL就可以将它放在页面上了,所以File API还有另外一种方法直接获取文件的URL。
- window.URL.createObjectURL(file):创建对象URL,传入file对象,返回值为一个字符串,指向一块内存的地址。
- window.URL.revokeObjectURL(url):释放对象URL占用的内存。
var inp = document.getElementById('myFile');
var progressDiv = document.getElementById('progress');
var completeDiv = document.getElementById('complete');
inp.addEventListener('change',function() {
// 获取上传的文件对象
var file = this.files[0];
// 创建对象URL,传入文件对象,获取其URL
var url = window.URL.createObjectURL(file);
console.log(url); // blob:null/f402d1d7-0bfb-407d-873e-a5d72324115e 字符串,指向内存的地址
// 直接将URL赋值给图片的src
var img = '<img src="' + url + '">';
completeDiv.innerHTML = img;
});
以上代码同样能实现相同效果:
HTML5的File API 很强大,但是兼容性存在问题,支持File API 的浏览器为IE10+、Safari 5.0+、Opera 11.1+ ,Firefox和Chrome完美支持,所以想兼容IE的话,呵呵.......