过去Web程序不能替代桌面程序的一个重要原因就在于浏览器对于文件操作API的缺失。照片处理中的裁剪、滤镜,二维码的读取与识别,文档的查看和编辑等,这些操作无一不依赖文件的操作,HTML5赋予了浏览器几乎和本地程序同等强大的文件操作能力。
File API是HTML5在DOM标准中添加的功能,它允许Web内容在用户授权的情况下选择本地文件并读取内容一通过 File,FileList 和FileReader等对象共同作用来实现。
选择文件
1、通过表单选择文件
由于Web环境的特殊性,为了考虑文件安全问题,浏览器不允许JavaScript直接访问文件系统,但可以通过file类型的input元素或者拖放的方式选择文件操作。
<input type="file" id="thisFile"/>
File表单可以让用户选取一个或者多个文件(multiple 属性),通过FileAPI,可在用户选择文件后访问到代表了所选文件列表的FileList对象,FileList 对象是一个类数组的对象,其中包含着一个或多个File对象。如果没有multiple属性或者用户只选了一个文件,那么只需要访问FileList对象的第一个元素:
var filelist=document.getElementById('thisFile') .files;
var selectedFile-filelist[0];
使用input元素时,用户在选择文件后会触发其change事件:
var inputElement=document.getElementById('thisFile')
inputElement. addEventListener ("change",handleFiles, false)
function handleFiles(){
var fileList=this.files
}
和其他类数组对象一样,FileList 也有length属性,可以轻松遍历其File对象:
for (var i=0, numFiles=files.length ; i< numFiles; i++) {
var file=files[i]
……
}
File对象有3个很有用的属性,包括了关于该文件的许多有用信息。
(1) name: 文件名,不包含路径信息。
(2) size: 文件大小,以B为单位。
(3) type:文件的MIME type。
需要注意的是,这3个属性都是只读的。
2、通过拖曳来选择文件
使用拖曳的方式来选择文件的效果,需要通过访问dataTransfer的files属性来实现。
下面通过一个案例来演示具体效果,如示例所示。
【示例】 使用拖曳的方式选择文件
<!DOCTYPE html>
<html>
<head lang="en">
<meta charset="UTF-8">
<title></title>
</head>
<style>
.dropzone{
width: 200px;
height: 100px;
border: 2px dashed #ddd;
text-align: center;
padding-top: 100px;
color: #999;
}
</style>
<body>
<div id="dropzone" class="dropzone">
拖曳文件到此处
</div>
<div id="output" class="output">
</div>
<script>
function getFileInfo(file) {
var aMultiples = ["KB", "MB", "GB", "TB", "PB", "EB", "ZB", "YB"], sizeinfo;
var info = '文件名:' + file.name ;
// 计算文件大小的近似值
for (var nMultiple = 0, nApprox = file.size / 1024; nApprox > 1; nApprox /= 1024, nMultiple++) {
sizeinfo = nApprox.toFixed(3) + " " + aMultiples[nMultiple] + " (" + file.size + " bytes)";
}
info += ";大小:" + sizeinfo
info += ";类型:" + file.type
return info + '<br>'
}
var dropzone = document.getElementById('dropzone');
dropzone.addEventListener('drop', function (e) {
var html = '您一共选择了 ' + e.dataTransfer.files.length + '个文件,文件信息如下:<br>';
[].forEach.call(e.dataTransfer.files, function (file) {
html += getFileInfo(file);
});
document.getElementById('output').innerHTML = html
e.preventDefault();
e.stopPropagation();
}, false);
dropzone.addEventListener('dragover', function (e) {
if (e.preventDefault) {
// 必须要阻止dragover的默认行为(即不可drop),这样才能进行drop操作。
// 否则不会触发drop事件
e.preventDefault();
}
return false
}, false)
</script>
</body>
</html>
用Chrome浏览器访问示例。
操作文件
1、FileReader 对象
前面讲到表单或者dataTansier对象中的File类型的实例代表着这个文件,但是这个文件对象只能访问到一些基本的信息(大小和文件名等),如果要访问文件的具体内容,还得借助FileReader对象。
FileReader对象可以将文件对象转换为字符串、DataURL对象或者二进制字符串等,以进行进一步操作。例如,在做图片上传功能时,可以先对选择的图片进行预览或者剪裁,待用户确认无误后再进行上传,可以节省许多不必要的带宽。以前文的拖曳文件例子为基础,加上拖曳图片预览功能,代码如示例所示。
【示例】 FileReader对象
<!DOCTYPE html>
<html>
<head lang="en">
<meta charset="UTF-8">
<title></title>
</head>
<style>
.dropzone {
width: 200px;
height: 100px;
border: 2px dashed #ddd;
text-align: center;
padding-top: 100px;
color: #999;
}
.preview img {
width: 100px;
height: 100px;
}
</style>
<body>
<div id="dropzone" class="dropzone">
拖拽文件到此处
</div>
<div id="preview" class="preview">
</div>
<script>
function handleFiles(files) {
var preview = document.getElementById('preview')
for (var i = 0; i < files.length; i++) {
var file = files[i]
// 用来过滤非图片类型
var imageType = /image.*/
if (!file.type.match(imageType)) {
continue
}
// 只能动态创建img对象来进行预览
var img = document.createElement("img")
// 将文件对象存起来
img.file = file
// 新建 FileRead 对象——是不是很简单?
var reader = new FileReader()
// FileReader在读取文件时是异步执行的(JS中许多对象都有类似API),因此需
要通过绑定其load事件来访问文件读取的结果
// 要注意,这里使用了闭包,因为img只保存当前函数(handleFiles)内的引用,
for循环并不会创建新的作用域
// 因此要通过一个闭包的形式拷贝一份img的引用,否则img在for循环结束后将
只引用最后一次创建的img元素。
reader.onload = (function(aImg) {
return function(e) {
// e.target.result 包含读取到的 dataURL信息
aImg.src = e.target.result
// 将图片插入当前文档
preview.appendChild(aImg)
}
})(img)
reader.onprogress = function (e) {
console.log('当前已加载:' + (e.loaded / e.total * 100).toFixed(2)
+ '%')
}
// readAsDataURL方法将file对象读取为dataURL
reader.readAsDataURL(file)
}
}
var dropzone = document.getElementById('dropzone')
dropzone.addEventListener('drop', function (e) {
handleFiles(e.dataTransfer.files)
e.preventDefault()
e.stopPropagation()
}, false)
dropzone.addEventListener('dragover', function (e) {
if (e.preventDefault) {
e.preventDefault()
}
return false
}, false)
</script>
</body>
</html>
用浏览器访问该页面。
从上面的例子可以看到FileReader()的基本用法。readAsDataURL()方法用于读取文件,它接收一个File 或者Blob对象的实例作为参数,并将文件内容转换为一个base64编码的URL字符串,并通过load事件将结果传递到e.target.result上。FileReader对象除了readAsDataURL()方法外,还有其他几个方法用于读取文件内容的操作。
(1) readAsArrayBuffer(Blob|File): 读取文件,最后result属性将包含ArrayBuffer对象以表示文件内容。ArrayBuffer 对象用来表示固定长度二进制数据的缓冲区。
(2) readAsBinaryString(Blob|File):读取文件, result属性包含文件的原始二进制数据。每个字节均由一个[0.255]范围内的整数表示。
(3) readAsText(BloblFile,encoding): 以文本方式读入文件,并可以指定返回数据的编码,默认为UTF-8。
(4) abort): 终止正在进行的读取操作。如果FileReader 对象没有进行读取操作,调用此方法会抛出DOM_FILE_ABORT_ERR异常。
2、Blob 对象
以上读取文件操作的方法有两个共同点,一是都接受一个 Blob或File类型的对象。
var fileParts=['<a>hey man</a>'];
var myB1ob=new B1ob (fileParts,{ "type":"text/xml"});
Blob对象还支持slice() 方法,用于对数据进行切割:
var yourBlob = myB1ob.slice (10,20) ;
File对象同样继承了Blob的slice()方法,可以利用此方法对File对象预先进行分割,然后再读取、上传,最后在服务器端进行组装——异步上传的原理就是这样。如果再记住分割点,这样即使网络中途断掉,也可以在下次传输时从断点续传。
除了都接受Blob和File对象,这些方法另外一个共同点是,由于JavaScript本身基于事件驱动,这些和平台相关的方法都是异步方法。即调用时立即返回,读取文件操作完成后再触发相应的load事件。
除了load事件,FileReader 对象还会调用这样一些事件处理程序。
(1) onabort:当读取操作被终止时调用(调用abort 方法)
(2) one rror: 当读取操作发送错误时调用。
(3) onl oad: 当读取操作成功完成时调用。
(4) onl oadend:当读取操作完成时调用,不管是成功还是失败,该处理程序在onload或者onerror后调用。
(5) onl oadstart: 当读取操作将要开始之前调用。
(6) onprogress:在读取数据过程中周期性调用。该事件为最有用的事件,在加载较大的文件时,可以提供一个进度条让用户知道当前加载进度,不让用户产生焦躁感。
reader.onprogress= function(e) {
console.log('当前文件已加载'+ e.loaded/e. total*100.toFixed(2)+'%')
}
e.total存储着当前文件的总大小(字节),e.loaded 表示当前文件已经加载了多少。
要想将图片文件转换成可以直接在HTML里引用的URL,除了前文提到的readAsDataURL()方法,还可以使用window.URL .createObjectURL()方法:
var objectURL =window.URL. crea teObjectURL (file0bj) ;
objectURL最后会得到一个类似blob: null/a672ae4c- f84e- 45d2- -87ae-f45dc986d601的字符串,这个字符串可以直接被IMG等元素引用。
objectURL和dataURL一样可以直接被img的src属性引用,就像Windows平台下的文件句柄或者Linux下的文件描述符,在使用完之后通常还要调用window.URL.revokeObjectURL()方法进行释放,如果不显示调用该方法,objectURL 将会在文档卸载时自动释放。对于前文的例子可以简单修改为URL对象版本:
function handleFiles (files) {
var preview=document.getElementById('preview')
for(var i=0;i<files.length;i++) {
var file=files [i]
……
var img=document.createElement("img")
img.src=window. URL.createObjectURL(file)
img.onload= function(e) {
window.URL.revoke0bjectURL(this.src)
}
Preview. appendChild (img)
}
}
有了操作文件的利器,读者可以做一些有趣的功能,比如实现类似Photoshop中图片处理的滤镜或者读取PDF文档并转换为HTML格式等
标签:Web,基于,读取,img,文件,对象,HTML5,file,var From: https://www.cnblogs.com/xmxit/p/17265841.html