前端文件对象
本文主要介绍Blob、File、FileReader和Canvas已经URL等对象属性及作用,最后结合工作遇到的问题介绍他们的应用场景。
Blob
Blob对象表示不可变得类似文件对象的原始数据。Blob表示不一定是JavaScript原生形式的数据。
构造函数:构造函数返回一个新的Blob对象。blob的内容由参数数组中给出的值串联组成。
var blob = new Blob(array,options)
-
参数array是一个由ArrayBuffer,ArrayBufferView,Blob,DOMString等对象构成的Array,或者其他类似对象的混合体,它将会被放进Blob。其中DOMString会被编码为UTF-8.
-
options 是一个可选的BlobPropertyBag字典,它可能会指定如下两个属性:
- type,默认值为”“,它代表了将会被放入到blob中的数组内容的MIME类型。
- endings,默认值为”transparent”,用于指定包含行结束符\n的字符串如何被写入。它是以下两个值中的一个: “native”,代表行结束符会被更改为适合宿主操作系统文件系统的换行符,或者 “transparent”,代表会保持blob中保存的结束符不变。
从blob中读取数据:从Blob中读取内容内容的唯一方法是使用FileReader。以下代码将Blob的内容作为类型数组读取:
var reader = new FileReader();
reader.addEventListener("loadend", function() {
// reader.result 包含转化为类型数组的blob
});
File
File接口基于Blob,继承了blob的功能并将其扩展使其支持用户系统上的文件。File接口提供有关文件的信息,并允许网页中的 JavaScript 访问其内容。
FileReader
FileReader 对象允许Web应用程序异步读取存储在用户计算机上的文件(或原始数据缓冲区)的内容,使用 File 或 Blob 对象指定要读取的文件或数据。
方法
| 方法定义 | 描述 |
|---|---|
| abort():void | 终止文件读取操作 |
| readAsArrayBuffer(file):void | 异步按字节读取文件内容,结果用ArrayBuffer对象表示 |
| readAsBinaryString(file):void | 异步按字节读取文件内容,结果为文件的二进制串 |
| readAsDataURL(file):void | 异步读取文件内容,结果用data:url的字符串形式表示 |
| readAsText(file,encoding):void | 异步按字符读取文件内容,结果用字符串形式表示 |
事件
| 方法定义 | 描述 |
|---|---|
| onabort | 终止文件读取操作 |
| onerror | 异步按字节读取文件内容,结果用ArrayBuffer对象表示 |
| onload | 异步按字节读取文件内容,结果为文件的二进制串 |
| onloadend | 异步读取文件内容,结果用data:url的字符串形式表示 |
| onloadstart | 异步按字符读取文件内容,结果用字符串形式表示 |
| onprogress | 在读取数据过程中周期性调用 |
Canvas
canvas中有toDataURL函数,可以将canvas转为dataURL形式的base64编码。
URL
调用 URL 对象的 createObjectURL 方法,传入一个 File 对象或者 Blob 对象,能生成一个链接。
var objecturl = window.URL.createObjectURL(blob);
上面的代码会对二进制数据生成一个 URL,这个 URL 可以放置于任何通常可以放置 URL 的地方,比如 img 标签的 src 属性。需要注意的是,即使是同样的二进制数据,每调用一次 URL.createObjectURL 方法,就会得到一个不一样的 URL。
项目中遇到的例子
在项目需要实现一个功能,就是表单内容的缓存,而表单内容涉及到File文件,其实就是图片封面。当用户跳转之后,原先选择的内容会有所保存,再跳转回来之后就会自动填充。缓存采用的是localStorage,但是localStorage只能存储字符串,不能直接存储文件对象,所以需要将图片文件转化成base64编码的字符串,想到两种方法:
使用Canvas
function toBase64(file){
let storageFiles={},
elephant = document.getElementById("dialogImage"),
date = new Date(),
todayDate = (date.getMonth()+1).toString()+date.getDate().toString();
localStorage.removeItem("storageFiles");
elephant.addEventListener("load", function () {
let imgCanvas = document.createElement("canvas");
let imgContext = imgCanvas.getContext("2d");
imgCanvas.width = elephant.width;
imgCanvas.height = elephant.height;
imgContext.drawImage(elephant, 0, 0, elephant.width, elephant.height);
storageFiles.elephant = imgCanvas.toDataURL("image/png");
storageFiles.date = todayDate;
try {
localStorage.setItem("storageFiles", JSON.stringify(storageFiles));
} catch (e) {
console.log("Storage failed:" + e);
}
})
}
使用FileReader
function toBase64(file){
let storageFiles = {};
storageFiles.date = new Date();
storageFiles.name = file.name;
let reader = new FileReader();
reader.onload = function() {
storageFiles.elephant = reader.result;
try {
localStorage.setItem("storageFiles", JSON.stringify(storageFiles));
} catch (e) {
console.log("Storage failed:" + e);
}
};
reader.readAsDataURL(file);
}
将base64编码的字符串转化成文件:
function toFile(){
let storageFiles = JSON.parse(localStorage.getItem("storageFiles")) || {};
if(storageFiles.elephant){
let arr = storageFiles.elephant.split(','),mime = arr[0].match(/:(.*?);/)[1],
bstr = atob(arr[1]), n = bstr.length, u8arr = new Uint8Array(n);
while(n--){
u8arr[n] = bstr.charCodeAt(n);
}
let theFile = new Blob([u8arr], {type:mime});
let fileArr = [];
fileArr.push(theFile);
thiz.ruleForm.file = new File(fileArr, storageFiles.name, {type: mime});
}
}
PS:canvas转换法转换之后是两张不一样的图片。