美文网首页
Web Api中的Blob到底是个啥?

Web Api中的Blob到底是个啥?

作者: 白羊座的泰迪 | 来源:发表于2022-10-31 02:48 被阅读0次

    前言

    有幸在一个后台上传大文件的需求中了解到了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()】

    相关文章

      网友评论

          本文标题:Web Api中的Blob到底是个啥?

          本文链接:https://www.haomeiwen.com/subject/mulltdtx.html