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会更加容易。

  • 相关阅读:
    Oracle EBS OM 主要API示例
    WIP 投料报 Invalid Serial Number
    物料事务处理interface与temp解析
    INV_TXN_MANAGER_PUB.PROCESS_TRANSACTIONS
    FND Debug Log(FND_LOG_MESSAGES)
    Oracle Apps DBA 常用命令
    详解EBS接口开发之WIP模块接口
    使用Java管理千台规模Linux服务器_入门
    windows下spark开发环境配置
    零成本实现Android/iOS自动化测试:基于Appium和Test Perfect
  • 原文地址:https://www.cnblogs.com/danceonbeat/p/10741187.html
Copyright © 2011-2022 走看看