File & FileReader & FileList & Blob & URL scheme 这几个方法或者说是“接口”都是一同被定义在了 W3C File API 的规范之中。
如果要画一张关系图的话,按照理解应该是这样的:
最初被 Google 使用的时候叫做 Binary Large Object ,表示不可变的原始二进制数据
new Blob(blobParts : Array, [blobPropertyBag : Object]) : Blob
blobPropertyBag : {
type String A valid mime type such as 'text/plain'
endings String Must be either 'transparent' or 'native'
}
Blob 第一个参数可以接受的数据类型有:
BufferSource
elements.Blob
elements.USVString
elements.第二个参数可以接受
var blob = new Blob(['foo', 'bar']);
console.log('size=' + blob.size);
console.log('type=' + blob.type);
var testEndings = function(string, endings) {
var blob = new Blob([string], { type: 'plain/text',
endings: endings });
var reader = new FileReader();
reader.onload = function(event){
console.log(endings + ' of ' + JSON.stringify(string) +
' => ' + JSON.stringify(reader.result));
};
reader.readAsText(blob);
};
testEndings('foo\nbar', 'native');
testEndings('foo\r\nbar', 'native');
testEndings('foo\nbar', 'transparent');
testEndings('foo\r\nbar', 'transparent');
size=6
type=
native of "foo\nbar" => "foo\nbar"
native of "foo\r\nbar" => "foo\nbar"
transparent of "foo\nbar" => "foo\nbar"
transparent of "foo\r\nbar" => "foo\r\nbar"
var blob = new Blob(['foo', 'bar'], { type: 'plain/text',
endings: 'native' });
console.log(blob.type); // plain/text
var blob = new Blob(['foo', 'bar'], { type: 'plain/text',
endings: 'native' });
console.log(blob.size); // 6
slice 顾名思义,和数组的 slice 差不多,传入起始位置 start 和终止位置 end,截取的内容是从 start ~ end – 1 区间的内容,如果传入负数和超过长度的值,则会根据具体的规则进行调整,不做赘述,可以看具体规范定义的。
var blob = new Blob(['foo', 'bar'], { type: 'plain/text',
endings: 'native' });
console.log('blob size:', blob.size); // blob size: 6
console.log('blob type:', blob.type); // blob type: plain/text
var copy = blob.slice()
console.log('copy size:', copy.size); // copy size: 6
console.log('copy type:', copy.type); // copy type:
var slice = blob.slice(1, 4, 'foo-type')
console.log('slice size:', slice.size); // slice size: 3
console.log('slice type:', slice.type); // slice type: foo-type
steam ,arrayBuffer,和 text 在兼容性上比较差,,steam 是用 ‘流’ 的方式返回,text 方法返回 promise, then 方法中可以拿到完整的 blob 内容。
var blob = new Blob(['abcd'])
blob.text().then(res => {
console.log(res) // abcd
})
兼容性:
File 对象继承自 Blob,并增加了几个属性用于描述该对象。
new File(fileParts : Array, name : String, [filePropertyBag : Object]) : File
filePropertyBag : {
type String A valid mime type such as 'text/plain'
endings String Must be either 'transparent' or 'native'
lastModified long
}
File 第一个参数可以接受的数据类型有:
BufferSource
elements.Blob
elements.USVString
elements.第二参数:name, 指定文件名
第三参数: 接收一个对象, 比 Blob 多了一个字段, lastModified
用来指定修改时间。
构造一个 File 对象:
var d = new Date(2020, 08, 01, 16, 23, 45, 600);
var generatedFile = new File(["Rough Draft ...."], "Draft1.txt", {type: "text/plain", lastModified: d})
一个包含所有 File 文件集合的 list。可以通过在 file 标签上指定 multiple 来让用户可以多选文件。通过类似数组下标的方式获取对应的 File 对象。
<input id='file-input' type='file' multiple>
<script>
var fileInput = document.getElementById('file-input');
fileInput.addEventListener('change', function(event) {
var input = event.target;
for (var i = 0; i < input.files.length; i++) {
console.log(input.files[i].name);
}
});
</script>
提供异步读取方法,可以通过事件监听的方式来异步的获取文件的数据,可以读取 File 和 Blob 对象的内容。
写了一个 Demo 用于读取本地文件,并展示读取进度条的例子🌰:
See the Pen file read progress by hjoker (@hjoker) on CodePen.
由于本质上是读取文件并加载到内存中,所以不推荐直接读取大文件,因为这样会导致浏览器占用过多内存,即便浏览器内部会适时的释放内存,但是依旧会碰到无响应的后果。
FileReader 有一个方法 readAsDataURL
,它可以自动帮你生成对应文件的 Base64 字符串,并在 onload 时候触发,可以从 result
属性中获取到。
再看一眼下面这张图是不是和 XMLHttpRequest
很类似?有 onload error 一系列方法。同样需要注意,载入过大的文件尺寸会影响浏览器计算 Base64 的速度。
See the Pen FileReader get Base64 by hjoker (@hjoker) on CodePen.
列一下 state
的几种状态。 初始状态是 Empty
也就是 0。
var reader = new FileReader()
> reader.readyState
0
> FileReader.EMPTY
0
> FileReader.LOADING
1
> FileReader.DONE
2
See the Pen FileReader state by hjoker (@hjoker) on CodePen.
触发事件:
方法:
readAsArrayBuffer(blob)
—— 将数据读取为二进制格式的 ArrayBuffer
。readAsText(blob, [encoding])
—— 将数据读取为给定编码(默认为 utf-8
编码)的文本字符串。readAsDataURL(blob)
—— 读取二进制数据,并将其编码为 base64 的 data url参考出处: