Open Cuuube opened 7 years ago
前几天看代码时,偶尔发现某站video元素的src里藏着没见过的科技。
就像这样:
<video src="blob://xxxxx.xxxx.xx/adasdasd"></video>
当时没时间,便加入长期观察。最近偶然看到类似字眼:“Blob对象”。便突然找到线索,搜索文档,写demo,差不多弄懂了这玩意是怎么形成,怎么运作的。
URL.createObjectURL()
首先最奇怪的莫过是“blob://xxx”这个奇怪的,像是“http://”,“ftp://”这种,像一种协议。
但却把他们复制到地址栏里却什么都没。
搜索文档后,看到了这个H5对象:blob。
里面有这么一句:
var url = URL.createObjectURL(blob); // 会产生一个类似blob:d3958f5c-0777-0845-9dcf-2cb28783acaf 这样的URL字符串
直译为生产带有对象的url
生产带有对象的url
看来URL.createObjectURL()这个方法会直接生成带blob的这种url。
blob
于是随手去控制台试了试:
不行,并不能随便传入obj。仔细观察,上面例子有传入一个blob,这说明,blob类要出场了。
文档是这么说的:
要从其他非blob对象和数据构造一个Blob,请使用 Blob() 构造函数。要创建包含另一个blob数据的子集blob,请使用 slice()方法。要获取用户文件系统上文件的Blob对象,请参阅 File文档。
Blob()
slice()
File
构造函数例子:
let personJson = `{"name":"Tom","age":15}`; let blob = new Blob([personJson], { type: 'application/json' });
文件内容放到第一个参数的数组中,第二个参数options中type指定类型。
上文我根据一段简单的json创建了个blob对象。此blob可以看做为文件系统级的.json文件。
.json
如果我们打印出该blob对象,只能看到如下:
> Blob {size: 23, type: "application/json"} > size:23 > type:"application/json" > __proto__:Blob
只能看到size和type,无法看到内部文件内容。因为内部文件内容已经不是js文本格式了,而是application/json文件格式。
application/json
当然,blob还能存储其他文件格式,如图片,视频,二进制数组等。在构造函数中指定正确的type即可。
(有些坑我还没踩,比如怎么把png的二进制传到blob构造函数里,用什么js对象当容器装png二进制。)
如果说Blob是一个隐藏在最深处的幕后黑手的话,FileReader就是闯进虎穴,将Blob拉到灯光下,扒了个干净。。。
好吧,其实就是一个阅读文件的接口。
FileReader可以读出blob的二进制文件,也能获得包含Blob文件信息的url(最开始说的那种)。
//基本使用, 比如要从上面blob变量还原出json: let reader = new FileReader(); reader.onload = function (e) { console.log(e.target.result); }; reader.readAsText(blob); //> {"name":"Tom","age":15}
readAsText为将读取结果作为文本输出。
readAsText
还有常用的为readAsDataURL,将读取结果作为包含Blob文件信息的url(最开始说的那种)。例子:
readAsDataURL
let reader = new FileReader(); let image = document.getElementById('img'); // 假如有个#img的元素 reader.onload = function (e) { let url = e.target.result; image.src = url; } reader.readAsDataURL(imageBlob); // 假如有一个包含图片文件的blob
这里用了onload方法,onload会在读取成功完成后,调用。
onload
和它相似的还有onloadend,读取结束之后,不管成功或失败都会调用。
onloadend
都知道,在文件上传时,可以获得input[type="file"]元素的file对象。
input[type="file"]
let input = document.querySelector('input[type="file"]'); input.onchange = function (e) { let file = this.files[0]; // 操作file... }
你如果console.log出来file,会看到,file对象包含文件名,文件大小等信息,但看不到二进制文件。
是不是很熟悉?对,File对象和Blob非常相似!
其实相似是正常的,因为他们是父子关系。如果在控制台里看file对象的__proto__,就能看到,File继承自Blob。
__proto__
所以我们平时在做图片文件上传的预览时,其实就是用FileReader扒开了File,将其图片内核赋给了img元素。所以我们才不用加载文件就能看到图。因为文件内容已经包含在了小小的URL里了啊!
最后,某站的video里,用的还有个MediaSource技术,专门处理流媒体文件的。有兴趣的可以直接戳进链接了解。
怎么得到真实的url呢?
Blob与FileReader
背景
前几天看代码时,偶尔发现某站video元素的src里藏着没见过的科技。
就像这样:
当时没时间,便加入长期观察。最近偶然看到类似字眼:“Blob对象”。便突然找到线索,搜索文档,写demo,差不多弄懂了这玩意是怎么形成,怎么运作的。
神秘url的生产者——
URL.createObjectURL()
首先最奇怪的莫过是“blob://xxx”这个奇怪的,像是“http://”,“ftp://”这种,像一种协议。
但却把他们复制到地址栏里却什么都没。
搜索文档后,看到了这个H5对象:blob。
里面有这么一句:
直译为
生产带有对象的url
看来
URL.createObjectURL()
这个方法会直接生成带blob
的这种url。于是随手去控制台试了试:
不行,并不能随便传入obj。仔细观察,上面例子有传入一个blob,这说明,blob类要出场了。
幕后主使——Blob对象
文档是这么说的:
构造函数例子:
文件内容放到第一个参数的数组中,第二个参数options中type指定类型。
上文我根据一段简单的json创建了个blob对象。此blob可以看做为文件系统级的
.json
文件。如果我们打印出该blob对象,只能看到如下:
只能看到size和type,无法看到内部文件内容。因为内部文件内容已经不是js文本格式了,而是
application/json
文件格式。当然,blob还能存储其他文件格式,如图片,视频,二进制数组等。在构造函数中指定正确的type即可。
(有些坑我还没踩,比如怎么把png的二进制传到blob构造函数里,用什么js对象当容器装png二进制。)
扒光Blob的英雄——FileReader
如果说Blob是一个隐藏在最深处的幕后黑手的话,FileReader就是闯进虎穴,将Blob拉到灯光下,扒了个干净。。。
好吧,其实就是一个阅读文件的接口。
FileReader可以读出blob的二进制文件,也能获得包含Blob文件信息的url(最开始说的那种)。
readAsText
为将读取结果作为文本输出。还有常用的为
readAsDataURL
,将读取结果作为包含Blob文件信息的url(最开始说的那种)。例子:这里用了
onload
方法,onload会在读取成功完成后,调用。和它相似的还有
onloadend
,读取结束之后,不管成功或失败都会调用。Blob 和 File的关系
都知道,在文件上传时,可以获得
input[type="file"]
元素的file对象。你如果console.log出来file,会看到,file对象包含文件名,文件大小等信息,但看不到二进制文件。
是不是很熟悉?对,File对象和Blob非常相似!
其实相似是正常的,因为他们是父子关系。如果在控制台里看file对象的
__proto__
,就能看到,File继承自Blob。
所以我们平时在做图片文件上传的预览时,其实就是用FileReader扒开了File,将其图片内核赋给了img元素。所以我们才不用加载文件就能看到图。因为文件内容已经包含在了小小的URL里了啊!
最后,某站的video里,用的还有个MediaSource技术,专门处理流媒体文件的。有兴趣的可以直接戳进链接了解。