Blob
Blob,Binary Large Object的缩写,二进制类型的大对象,代表不可改变的原始数据
在计算机中,BLOB常常是数据库中用来存储二进制文件的字段类型。 Blob基本用法
Blob对象
Blob对象指的是字节序列,并且具有size属性,是字节序列中的字节总数,和一个type属性,它是小写的ASCII编码的字符串表示的媒体类型字节序列。
size:以字节数返回字节序列的大小。获取时,符合要求的用户代理必须返回一个FileReader或一个FileReaderSync对象可以读取的总字节数,如果Blob没有要读取的字节,则返回0 。
type:小写的ASCII编码字符串表示媒体类型Blob。在获取时,用户代理必须Blob以小写形式返回a类型的ASCII编码字符串,这样当它转换为字节序列时,它是可解析的MIME类型,或者是空字符串(0字节)如果是类型无法确定。
构造函数
创建blob对象本质上和创建一个其他对象的方式是一样的,都是使用Blob() 的构造函数来进行创建。 构造函数接受两个参数:
第一个参数为一个数据序列,格式可以是ArrayBuffer, ArrayBufferView, Blob, DOMString
第二个参数是一个包含以下两个属性的对象
- type: MIME的类型,
- endings: 决定第一个参数的数据格式。默认值为"transparent",用于指定包含行结束符n的字符串如何被写入。 它是以下两个值中的一个: "native",表示行结束符会被更改为适合宿主操作系统文件系统的换行符; "transparent",表示会保持blob中保存的结束符不变。
ar
data1 = ``"a"``;
var
blob1 = ``new
Blob([data1]);
console.log(blob1); ``//输出:Blob {size: 1, type: ""}
var
debug = {hello: ``"world"``};
var
blob = ``new
Blob([JSON.stringify(debug, ``null``, 2)],{type : ``'application/json'``});
console.log(blob) ``// 输出 Blob(22) {size: 22, type: "application/json"}
// 创建一个8字节的ArrayBuffer,在其上创建一个每个数组元素为2字节的“视图”
var
abf = ``new
ArrayBuffer(8)
var
abv = ``new
Int16Array(abf)
var
bolb_ArrayBuffer = ``new
Blob(abv, {type : ``'text/plain'``})
console.log(bolb_ArrayBuffer) ``//输出 Blob(4) {size: 4, type: "text/plain"}
slice方法
Blob对象有一个slice方法,返回一个新的 Blob对象,包含了源 Blob对象中指定范围内的数据。
1 | slice(start, end, contentType) |
---|
start: 可选,代表 Blob 里的下标,表示第一个会被会被拷贝进新的 Blob 的字节的起始位置。如果传入的是一个负数,那么这个偏移量将会从数据的末尾从后到前开始计算。
end: 可选,代表的是 Blob 的一个下标,这个下标-1的对应的字节将会是被拷贝进新的Blob 的最后一个字节。如果你传入了一个负数,那么这个偏移量将会从数据的末尾从后到前开始计算。
contentType: 可选,给新的 Blob 赋予一个新的文档类型。这将会把它的 type 属性设为被传入的值。它的默认值是一个空的字符串。var
data = ``"abcdef"``;``var
blob1 = ``new
Blob([data]);``var
blob2 = blob1.slice(0,3);
console.log(blob1); ``//输出:Blob {size: 6, type: ""}``console.log(blob2); ``//输出:Blob {size: 3, type: ""}
| | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
slice用于文件分片上传
- 分片与并发结合,将一个大文件分割成多块,并发上传,极大地提高大文件的上传速度。
- 当网络问题导致传输错误时,只需要重传出错分片,而不是整个文件。另外分片传输能够更加实时的跟踪上传进度。
分片上传逻辑如下:
获取要上传文件的File对象,根据chunk(每片大小)对文件进行分片
通过post方法轮循上传每片文件,其中url中拼接querystring用于描述当前上传的文件信息;post body中存放本次要上传的二进制数据片段
接口每次返回offset,用于执行下次上传
12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091 | initUpload(); //初始化上传``function initUpload() {`` ``var chunk = 100 * 1024; ``//每片大小`` ``var input = document.getElementById(``"file"``); ``//input file`` ``input.onchange = ``function (e) {`` ``var file = ``this``.files[0];`` ``var query = {};`` ``var chunks = [];`` ``if (!!file) {`` ``var start = 0;`` ``//文件分片`` ``for (``var i = 0; i < Math.ceil(file.size / chunk); i++) {`` ``var end = start + chunk;`` ``chunks[i] = file.slice(start , end);`` ``start = end;`` ``}`` ``// 采用post方法上传文件`` ``// url query上拼接以下参数,用于记录上传偏移`` ``// post body中存放本次要上传的二进制数据`` ``query = {`` ``fileSize: file.size,`` ``dataSize: chunk,`` ``nextOffset: 0`` ``} ``upload(chunks, query, successPerUpload);`` ``}`` ``}``} // 执行上传``function upload(chunks, query, cb) {`` ``var queryStr = Object.getOwnPropertyNames(query).map(key => {`` ``return key + ``"=" + query[key];`` ``}).join(``"&"``);`` ``var xhr = ``new XMLHttpRequest();`` ``xhr.open(``"POST"``, ``"http://xxxx/opload?" + queryStr);`` ``xhr.overrideMimeType(``"application/octet-stream"``);`` ``//获取post body中二进制数据`` ``var index = Math.floor(query.nextOffset / query.dataSize);`` ``getFileBinary(chunks[index], ``function (binary) {`` ``if (xhr.sendAsBinary) {`` ``xhr.sendAsBinary(binary);`` ``} ``else {`` ``xhr.send(binary);`` ``} ``}); ``xhr.onreadystatechange = ``function (e) {`` ``if (xhr.readyState === 4) {`` ``if (xhr.status === 200) {`` ``var resp = JSON.parse(xhr.responseText);`` ``// 接口返回nextoffset`` ``// resp = {`` ``// isFinish:false,`` ``// offset:100*1024`` ``// }`` ``if (``typeof cb === ``"function"``) {`` ``cb.call(``this``, resp, chunks, query)`` ``}`` ``}`` ``}`` ``}``} // 每片上传成功后执行``function successPerUpload(resp, chunks, query) {`` ``if (resp.isFinish === ``true``) {`` ``alert(``"上传成功"``);`` ``} ``else {`` ``//未上传完毕`` ``query.offset = resp.offset;`` ``upload(chunks, query, successPerUpload);`` ``}``} // 获取文件二进制数据``function getFileBinary(file, cb) {`` ``var reader = ``new FileReader();`` ``reader.readAsArrayBuffer(file);`` ``reader.onload = ``function (e) {`` ``if (``typeof cb === ``"function"``) {`` ``cb.call(``this``, ``this``.result);`` ``}`` ``}``} |
---|---|
Blob URL |
blob协议的url使用时就像平时使用的url一样,可以作为图片请求地址,也可以作为文件请求地址。格式:
blob:http://XXX
- URL.createObjectURL(blob) 创建链接
- URL.revokeObjectURL(url)
下面是一个下载文件的示例,直接调用即可实现文件下载
123456789101112131415161718 | // file是要下载的文件(blob对象)``downloadHandler: ``function (file, fileName) {`` ``let link = document.createElement(``'a'``)`` ``link.href = window.URL.createObjectURL(file)`` ``link.download = fileName`` ``link.click()`` ``window.URL.revokeObjectURL(link.href)`` ``if (navigator.userAgent.indexOf(``'Firefox'``) > -1) {`` ``const a = document.createElement(``'a'``)`` ``a.addEventListener(``'click'``, ``function (e) {`` ``a.download = fileName`` ``a.href = URL.createObjectURL(file)`` ``})`` ``let e = document.createEvent(``'MouseEvents'``)`` ``e.initEvent(``'click'``, ``false``, ``false``)`` ``a.dispatchEvent(e)`` ``}``} |
---|
在从后台获取的数据接口中把返回类型设置为blob
12 | var x = ``new XMLHttpRequest();``x.responseType = ``'blob'``; ``// 返回一个blob对象 |
---|
Blob URL和Data URL的区别
Blob URL
Data URL
- Blob URL的长度一般比较短,但Data URL因为直接存储图片base64编码后的数据,往往很长,如上图所示,浏览器在显示Data URL时使用了省略号(…)。当显式大图片时,使用Blob URL能获取更好的可能性。
- Blob URL可以方便的使用XMLHttpRequest获取源数据,比如设置XMLHttpRequest返回的数据类型为blob
- Blob URL 只能在当前应用内部使用,把Blob URL复制到浏览器的地址栏中,是无法获取数据的。Data URL相比之下,就有很好的移植性,可以在任意浏览器中使用。