zoukankan      html  css  js  c++  java
  • 认识Js中的二进制数据

    Blob

    在项目中涉及到要对html原生的audio组件进行样式复写,因此需要重新实现audio的一些功能,比如下载。实现一个下载大致的思路是服务端返回一段音频的二进制数据,客户端将其存放在Blob中,再通过URL.createObjectURL将其转换成blob url,最后动态创建a标签,添加download属性,模拟点击事件来实现下载。代码比较简单,我们重点来看看Blob是何方神圣。

    const saveExcelFile = (blob, filename) => {
        if (window.navigator.msSaveOrOpenBlob) {
          // iE下使用msSaveBlob进行导出
          navigator.msSaveBlob(blob, filename)
        } else {
          var href = window.URL.createObjectURL(blob)
    
          var save_link = document.createElementNS(
            'http://www.w3.org/1999/xhtml',
            'a'
          )
          save_link.href = href
          save_link.download = filename
    
          // 解决火狐兼容问题
          document.body.appendChild(save_link)
    
          var event = document.createEvent('MouseEvents')
          event.initMouseEvent(
            'click',
            true,
            false,
            window,
            0,
            0,
            0,
            0,
            0,
            false,
            false,
            false,
            false,
            0,
            null
          )
          save_link.dispatchEvent(event)
    
          document.body.removeChild(save_link)
          // 释放blob url,可被GC回收
          window.URL.revokeObjectURL(href)
        }
    }
    

    根据MDN的介绍,我们可以知道Blob类型的对象是类似文件对象的二进制数据,它是immutable的,即数据不可变。而HTML5的File对象继承于Blob对象,并在其基础上做了些扩展,从而具备了在操作系统上操作文件的能力。我们可以利用Blob去做一些下载文件、分片上传等功能。熟悉ES6的小伙伴应该知道,ES6中有一个ArrayBuffer对象,也是用来存储二进制数据的,那它和Blob有什么区别呢?

    ArrayBuffer

    根据一些资料,ArrayBuffer设计的目的与WebGL项目有关,为了满足JS与显卡或声卡等操作系统原生接口大量的、实时的数据交换。传统的文本格式是传递一个32位的整数,这导致JS与原生接口需要频繁的转换数据格式,效率较低,因此设计了ArrayBuffer用于存储、操作二进制数据。
    ArrayBuffer并不是真正的Array,而是个类数组对象。我们通过new ArrayBuffer(length)创建的ArrayBuffer的实例,仅仅代表开辟了一段连续的内存空间,length代表内存所占的字节大小。若需要对内存中的字节进行操作,则需要创建“视图”。视图分为两种:TypedArray和DataView,用于以指定的格式来读写二进制的数据。它们的区别在于:

    • TypedArray以指定的格式读写内存,例如:const v1 = new Int32Array(buffer)就是以32位有符号整型来创建视图,此时通过v1[0]去读或是去写都是以该格式进行的
    • 若是想以不同数据格式去读取内存的话,需要使用DataView。当我们执行const dv = new DataView(buffer)后,可以通过类似dv.getUint8(0)这样的方式,以8位无符号整型读取第一个字节;或是以dv.setInt32(1, 25)这种方式,在第二个字节写入值为25的32位有符号整型数据

    注意:对于同一段内存创建的视图都是共享该内存的,在一个视图上进行的操作会影响另一个视图的读写。具体的可参考阮老师的教程

    区别

    • ArrayBuffer可以对字节进行读写,而Blob是immutable的
    • ArrayBuffer存储在内存当中,Blob可以存储在磁盘或者内存中。例如文件,我们平时是存在磁盘中的。而像我们上面下载的例子中,我们的blob是在内存中的,因此在createObjectURL之后需要手动调用revokeObjectURL解除对内存的引用,使得blob可以被GC回收,释放内存。
    • ArrayBuffer可以通过“视图”来进行读写,而Blob可以通过FileReader去读,但是不能写
    • Blob和ArrayBuffer可以互相转换。Blob转ArrayBuffer可以通过:
      const reader = new FileReader()
      reader.onload = function() {
          console.log(reader.result)
      }
      reader.readAsArrayBuffer(blob)
      
      ArrayBuffer转Blob可以通过:
      const blob = new Blob([ArrayBuffer])
      

    因此,当我们需要对字节进行操作的时候,我们应该选用ArrayBuffer,否则,我们用Blob会更加容易。

  • 相关阅读:
    java基础部分的一些有意思的东西。
    antdvue按需加载插件babelpluginimport报错
    阿超的烦恼 javaScript篇
    .NET E F(Entity Framework)框架 DataBase First 和 Code First 简单用法。
    JQuery获得input ID相同但是type不同的方法
    gridview的删除,修改,数据绑定处理
    jgGrid数据格式
    Cannot read configuration file due to insufficient permissions
    Invoke action which type of result is JsonResult on controller from view using Ajax or geJSon
    Entity model数据库连接
  • 原文地址:https://www.cnblogs.com/danceonbeat/p/10741187.html
Copyright © 2011-2022 走看看