从设计模式出发,带你认识Blob、FileReader

从设计模式出发,带你认识Blob、FileReader

十二月 03, 2020 本文共计: 931 字 预计阅读时长: 4分钟

从设计模式入手,介绍BlobFileReader

虚拟代理模式

当提及虚拟代理时,你可能下意识的会想到proxy,虚拟代理的核心思想就是在目标对象身上架设起一座桥梁,为它去做一些额外的事。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
const target = {
message1: "hello",
message2: "everyone"
};

const handler3 = {
get (target, prop, receiver) {
console.log(target, prop, receiver)
if (prop === "message2") {
return "world";
}
return Reflect.get(...arguments);
},

set (target, prop, receiver) {
console.log('set', prop, target, receiver, this)
if (prop === 'message1') {
target[prop] = receiver
}
}
};

const proxy3 = new Proxy(target, handler3);

proxy3.message1 = 'ssdsd'

console.log(proxy3.message1); // ssdsd
console.log(proxy3.message2); // world

粘贴了MDNProxy示例,配合Reflect去做一些既保留原始行为,又可以自定义行为的功能。

同样的,虚拟代理的原理也很简单,拿一个图片的预加载举一个栗子

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
// 真实 dom 对象,以及行为   
class TDomObj {
constructor(obj) {
this.trueDom = obj;
}

setSrc (url) {
this.trueDom.src = url
}
}

// 代理真实 dom
class ProxyTDom {
constructor(TDom) {
this.TDom = TDom;
}

setSrc (url) {
// 预加载已设置好的预览图
this.TDom.setSrc('https://segmentfault.com/img/bVbIDbC');
// new 一个虚拟的 Image 对象
const img = new Image();
img.onload = () => {
// 监听虚拟 img 加载完毕后,平滑 set
this.TDom.setSrc(url);
}
// 虚拟 img 对象去加载真实 img 资源
img.src = url;
}
}

那么,有人会问了,这些跟 BlobFileReader有什么关系呢?

FileReader

FileReader可以读取用户计算机上的二进制文件。以Blob对象的数据格式去处理。

怎么获取用户计算机文件呢?

  1. 利用input手动上传,监听change

  2. 利用ajax获取服务端文件,可以设置responseTypeBlob对象。

(小tip: 阿里 OSS 的图片、文件(pdf等)CDN是不支持预览的,可以借助ajax获取服务端文件,以Blob形式获取后,创建Blob URL,利用createObjectURL(:blob)生成,window.open预览)

Blob

Blob是一种原始数据对象(其实就是二进制数据对象);【File继承自Blob

File继承自Blob,所以也就可以引申我们接下来要提到的,图片分片上传,利用Blob对象的splice方法,它可以返回一个新的Blob对象。

相比于一般的base 64data url而言,Blob Url更短,字节数更少,所以文件也就很少,可以作为提升性能的一个手段,但是它的局限性在于只能在当前应用内使用,应为生成的Blob URL前缀为当前应用的根路径。不可以跨应用使用。

Now, Show My Time!!!

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport"
content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Document</title>

</head>
<body>
<input type="file" placeholder="请上传" id="UPLOAD">
<img id="OUTPUT" src=""/>
<script>
class TDomObj {
constructor(obj) {
this.trueDom = obj;
}

setSrc (url) {
this.trueDom.src = url
}
}

class ProxyTDom {
constructor(TDom) {
this.TDom = TDom;
}

setSrc (url) {
this.TDom.setSrc('https://segmentfault.com/img/bVbIDbC');
const img = new Image();
img.onload = () => {
this.TDom.setSrc(url);
}
img.src = url;
}
}

const tdom = document.getElementById('OUTPUT');

const t = new TDomObj(tdom);

const p = new ProxyTDom(t);

document.getElementById('UPLOAD').addEventListener('change', (e) => {
console.log(e);
const reader = new FileReader();
reader.onload = function () {
console.log(reader.result)
p.setSrc(reader.result)
}
reader.readAsDataURL(e.target.files[0]);
})
</script>
</body>
</html>
  • 自律并不可怕,可怕的是坚持自律。