Web Api中的Blob到底是个啥?

前言

有幸在一个后台上传大文件的需求中了解到了Blob,其实真正接触Blob对象是在下载电影的时候,现在很多video标签的src路径是blob格式,当时只知道是流媒体,Blob还带着一层面纱,那么Blob到底是个啥,这里来浅谈一下~

一、Blob对象

Blob 对象表示一个不可变、原始数据的类文件对象。它的数据可以按文本或二进制的格式进行读取,也可以转换成 ReadableStream 来用于数据操作。
File 接口基于 Blob,继承了 blob 的功能并将其扩展以支持用户系统上的文件。

说人话:简单来讲,就是Blob可以将文件换成二进制格式,并对这个为二进制文件进行剪切和拼接操作,也是目前js唯一可以操作二进制的方式。

1、创建blob对象

var aBlob = new Blob( array, options );

参数:

array 是一个由ArrayBuffer, ArrayBufferView, Blob, DOMString 等对象构成的 Array ,或者其他类似对象的混合体,它将会被放进 Blob。DOMStrings 会被编码为 UTF-8。

options 是一个可选的BlobPropertyBag字典,它可能会指定如下两个属性:

  • type,默认值为 "",它代表了将会被放入到 blob 中的数组内容的 MIME 类型。
  • endings,默认值为"transparent",用于指定包含行结束符\n的字符串如何被写入。它是以下两个值中的一个:"native",代表行结束符会被更改为适合宿主操作系统文件系统的换行符,或者 "transparent",代表会保持 blob 中保存的结束符不变

举例:

var b1 = '<a id="a"><b id="b">hey!</b></a>'; // DOMString 
var b2 = '123';
var aBlob = new Blob([b1], {type:'text/html'} );
console.log(aBlob);
//Blob {size: 35, type: 'text/html'}

实例方法:

Blob实例对象有以下方法:不再一一详述,大家感兴趣可以点击方法名去文档做了解

  • slice():返回一个新的 Blob 对象,包含了源 Blob 对象中指定范围内的数据。
  • stream():返回一个能读取 blob 内容的 ReadableStream。
  • text():返回一个 Promise 对象且包含 blob 所有内容的 UTF-8 格式的 USVString。
  • arrayBuffer():返回一个 Promise 对象且包含 blob 所有内容的二进制格式的 ArrayBuffer

2、创建blob URL

平时我们常见到的还是blob URL
Blob url 是指向存储在浏览器缓存或磁盘中的blob的一个引用。

//格式如:
blob:https://www.jianshu.com/u/685589ccbc2a

Blob URL可以通过URL.createObjectURL(blob)创建。在绝大部分场景下,我们可以像使用Http协议的URL一样,使用Blob URL。常见的场景有:作为文件的下载地址和作为图片资源地址。

举例:

给上传图片创建一个Blob URL

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
</head>

<body>
    <input id="J_input" type="file"  onchange="handleFile(this)" />
    <br/>
    <img id="J_img" src="">
</body>
 <script>
         var img = document.getElementById('J_img');
         function handleFile(e) {
            var file = e.files[0];
            var blob = URL.createObjectURL(file);
            img.src = blob;
            img.onload = function(e) {
                URL.revokeObjectURL(this.src);  // 释放createObjectURL创建的对象##
            }
        }
    </script>
</html>
image中生成的blob Url

注:在每次调用 createObjectURL() 方法时,都会创建一个新的 URL 对象,即使你已经用相同的对象作为参数创建过。当不再需要这些 URL 对象时,每个对象必须通过调用 URL.revokeObjectURL() 方法来释放,清除占用内存。
浏览器在 document 卸载的时候,会自动释放它们,但是为了获得最佳性能和内存使用状况,你应该在安全的时机主动释放掉它们。

二、常用场景

当我们上传大文件时,传输速度过慢,如果中间断开链接,也会导致传输文件丢失,这时常用blob对象来进行分片上传
分片上传主要是用Blob对象的slice方法将原文件剪切成碎片,然后依次将碎片上传。

1、slice方法

Blob.slice() 方法用于创建一个包含源 Blob的指定字节范围内的数据的新 Blob 对象。
前边提到,Blob 对象是不可改变的。我们不能直接在一个 Blob 中更改数据,但是我们可以对一个 Blob 进行分割,从其中创建新的 Blob 对象,将它们混合到一个新的 Blob 中。这种行为类似于 JavaScript 字符串:我们无法更改字符串中的字符,但可以创建新的更正后的字符串。

var blob = instanceOfBlob.slice([start [, end [, contentType]]]};

参数:

  • start:可选

    • 这个参数代表 Blob里的下标,表示第一个会被会被拷贝进新的 Blob的字节的起始位置。
    • 如果你传入的是一个负数,那么这个偏移量将会从数据的末尾从后到前开始计算。举例来说,-10 将会是 Blob的倒数第十个字节。
    • 它的默认值是 0,如果你传入的 start 的长度大于源 Blob 的长度,那么返回的将会是一个长度为 0 并且不包含任何数据的一个 Blob对象。
  • end:可选

    • 这个参数代表 Blob里的下标,这个下表-1的对应字节将会呗拷贝进新的Blob的最后一个字节
    • 如果你传入一个负数,那么这个偏移量将会从数据的末尾从后往前开始计算。举例来说,-10 将会是 Blob的倒数第十个字节。
    • 它的默认值是他的原始长度(size)。
  • contentType:可选

    • 给新的Blob赋予一个新的文档类型。这将会把它的 type 属性设为被传入的值。它的默认值是 一个空的字符串。

举例

    var data = "12345678";
    var blob1 = new Blob([data]);
    var blob2 = blob1.slice(0,4);
    
    console.log(blob1);  //输出:Blob {size: 8, type: ""}
    console.log(blob2);  //输出:Blob {size: 4, type: ""}

2、分片上传

前面已经说过,File接口基于 Blob,继承了 blob 的功能并将其扩展以支持用户系统上的文件。因此我们可以调用File的slice方法对大文件进行分片长传。代码如下:

注:file.slice()返回的是blob对象

function uploadFile(file) {
  var chunkSize = 1024 * 1024;   // 每片1M大小
  var totalSize = file.size;//文件总长度
  var chunksNum = Math.ceil(totalSize / chunkSize);  //分片总数
  var index = 0;  // 分片的索引标记,记录是第几片
  
  var reader = new FileReader();
  reader.onload = function(e) {
    var xhr = new XMLHttpRequest();
    xhr.open("POST","http://xxxx/upload?fileName="+file.name);
    xhr.overrideMimeType("application/octet-stream");
    
    xhr.onreadystatechange = function() {
      if(xhr.readyState === XMLHttpRequest.DONE && xhr.status === 200) {
        ++index;
        if(index === chunksNum) {
          alert("上传完成");
        } else if(offset === chunksNum-1){
          blob = file.slice(index*chunkSize, totalSize);   // 上传最后一片
          reader.readAsBinaryString(blob);
        } else {
          blob = file.slice(index*chunkSize, (index+1)*chunkSize); 
          reader.readAsBinaryString(blob);
        }
      }else {
        alert("上传出错");
      }
    }
    
    if(xhr.sendAsBinary) {
      xhr.sendAsBinary(e.target.result);   // e.target.result是此次读取的分片二进制数据
    } else {
      xhr.send(e.target.result);
    }
  }
   var blob = file.slice(index, chunkSize);
   reader.readAsBinaryString(blob);//开始上传时读取第一片文件,第一次触发reader.onload
}

这个代码中用到了FileReader对象中的readAsBinaryString方法来读取blob文件片,并触发onload事件监听文件读取完成的时间节点,同时onload返回的 result 属性包含所读取文件原始二进制格式,也就是最终上传的文件内容。

注:

使用FileReader时,一定记住readAsBinaryString方法和onload成对使用,没有readAsBinaryString方法,则无法触发onload。

三、相关知识

1、【FileReader】
2、【URL.createObjectURL()】

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 159,716评论 4 364
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 67,558评论 1 294
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 109,431评论 0 244
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 44,127评论 0 209
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,511评论 3 287
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,692评论 1 222
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,915评论 2 313
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,664评论 0 202
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,412评论 1 246
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,616评论 2 245
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,105评论 1 260
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,424评论 2 254
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,098评论 3 238
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,096评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,869评论 0 197
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,748评论 2 276
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,641评论 2 271

推荐阅读更多精彩内容