项目中碰到一个需求,上传图片及时给用户预览。
开始的想法就是上传的图片先传递到后台,在通过ajax获取图片路径显示到前台。但这样做首先对后端开销比较大,也需要专门写一个接口来处理这个问题。能不能直接通过前端来解决呢?
翻了一下html5新的File API,发现有个FileReader类型,可以完美解决这个问题。
File API
file表单元素的files属性,可以获取文件对象数组。
通过file.files[0]可以获取对应的文件对象,一般有,larstModified,name,size,type几个属性。
<input type="file" id="file">
<script type="text/javascript">
var file = document.getElementById('file');
file.onchange = function() {
console.log(this.files[0].name, this.files[0].type, this.files[0].size);
}
</script>
当然这对图片上传预览没什么用,重要的是FileReader类型:
FileReader
FileReader提供如下的几个方法
-
readAsText(file [, encoding])
:以纯文本读取文件,读取到的结果返回。第二个参数为编码类型,可选。 -
readAsDataURL(file)
:将文件数据以URL的形式返回(常用来处理图片)。 -
readAsBinaryString(file)
:将文件以字符串形式返回(字符串中每个字符表示一字节)。 -
readAsArrayBuffer(file)
:将文件内容的ArrayBuffer返回。
FileReader提供了几个事件
- progress:传输过程触发的事件,事件对象有lengthComputable, loaded, total, result属性
- error:传输失败触发
- load:传输完成触发
案例:
<body>
<input type="file" id="files">
<div id="progress"></div>
<div id="prvid">预览容器</div>
<script type="text/javascript">
var files = document.getElementById('files');
var output = document.getElementById('prvid');
var progress = document.getElementById('progress');
files.onchange = function(ev) {
var file = ev.target.files[0];
var reader = new FileReader();
if (/image/.test(file.type)) {
reader.readAsDataURL(file);
type = 'image';
} else {
reader.readAsText(file);
type = 'text';
}
reader.onerror = function() {
output.innerHTML = '文件读取失败';
}
reader.onprogress = function(event) {
if (event.lengthComputable) {
progress.innerHTML = event.loaded + '/' + event.total;
}
}
reader.onload = function() {
var html = '';
switch(type) {
case 'image':
html = '![](' + reader.result + ')';
break;
case 'text':
html = reader.result;
break;
}
output.innerHTML = html;
}
}
</script>
</body>