(给前端大全加星标,提升前端技能)

作者:全栈成长之路 公号 / 山月行

作为一名前端,在工作中也会遇到很多有关二进制处理的需求,如 EXCEL 表格的导出,PDF 的生成,多个文件的打包,音频的处理。

从前后端整体上来说前端代表 UI 层,它的外在表现是 human readable 的,而服务端代表数据层,所表现出来的是 machine readable。如果 EXCEL 以及 PDF 的处理交由服务端处理,服务端免不了要做一层格式化的逻辑处理,以便与前端保持一致。一来增加了复杂度,二来容易造成前端与服务器端的数据不一致。此时为了减少复杂度,工作量有可能都尽可能在浏览器端完成。

本篇文章总结了浏览器端的二进制以及有关数据之间的转化,如 ArrayBufferTypedArrayBlobDataURLObjectURLText 之间的互相转换。为了更好的理解与方便以后的查询,特意做了一张图做总结。

二进制相互转换图

二进制相关数据类型

在介绍常见的二进制数据处理之前,先简单介绍下几种二进制相关的数据类型

ArrayBuffer && TypedArray

TypedArray 是 ES6+ 新增的描述二进制数据的类数组数据结构。但它本身不可以被实例化,甚至无法访问,你可以把它理解为 Abstract Class 或者 Interface。而基于 TypedArray,有如下数据类型:

  • Uint8ArrayUint 及 Unsigned Int 代表数组的每一项是无符号整型8 代表数据的每一项占 8 个比特位,即一个字节
  • Int8Array
  • Uint16Array
  • Int16Array
  • ...

通过 Uint8Array,即可知道 Uint16ArrayInt8Array 所代表的意义。

const array = new Int32Array([1, 2, 3])

// .length 代表数组的大小// 3array.length

// .btyeLength 代表数据所占字节大小// 12array.byteLength

ArrayBuffer 代表二进制数据结构,「并且只读」,需要转化为 TypedArray 进行写操作。

const array = new Int16Array([1, 2, 3])

// TypedArray -> ArrayBufferarray.buffer

// ArrayBuffer -> TypedArraynew Int16Array(array.buffer)

// buffer.length 代表数据所占用字节大小array.buffer.length === array.byteLength

连接多个 TypedArray

TypedArray 没有像数组那样的 Array.prototype.concat 方法用来连接多个 TypedArray。不过它提供了 TypedArray.prototype.set 可以用来间接连接字符串

可以参考 MDN 文档:https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/TypedArray/set

// 在位移 offset 位置放置 typedarraytypedarray.set(typedarray, offset)

原理就是先分配一块空间足以容纳需要连接的 TypedArray,然后逐一在对应位置叠加

function concatenate(constructor, ...arrays) {  let length = 0;  for (let arr of arrays) {    length += arr.length;  }  let result = new constructor(length);  let offset = 0;  for (let arr of arrays) {    result.set(arr, offset);    offset += arr.length;  }  return result;}

concatenate(Uint8Array, new Uint8Array([1, 2, 3]), new Uint8Array([4, 5, 6]))

同时您还需要对资源的获取有大致的了解,如 XHR,fetch,通过文件上传。

Blob

Blob 是浏览器端的类文件对象。操作 Blob 需要使用数据类型 FileReader

FileReader 有以下方法,可以把 Blob 转化为其它数据

  • FileReader.prototype.readAsArrayBuffer
  • FileReader.prototype.readAsText
  • FileReader.prototype.readAsDataURL
  • FileReader.prototype.readAsBinaryString
const blob = new Blob('hello'.split(''))

// 表示文件的大小blob.size

const array = new Uint8Array([128, 128, 128])const blob2 = new Blob([array])

function readBlob (blob, type) {  return new Promise(resolve => {    const reader = new FileReader()    reader.onload = function (e) {      resolve(e.target.result)    }    reader.readAsArrayBuffer(blob)  })}

readBlob(blob, 'DataURL').then(url => console.log(url))

数据输入

数据输入或者叫资源的请求可以分为以下两种途径

  • 通过 url 地址请求网络资源
  • 通过文件上传请求本地资源

fetch

fetch 应该是大家比较熟悉的,但大多使用环境比较单一,一般用来请求 json 数据。其实, 「它也可以设置返回数据格式为 Blob 或者 ArrayBuffer。」

fetch 返回一个包含 Response 对象的 Promise,Response 有以下方法

  • Response.prototype.arrayBuffer
  • Response.prototype.blob
  • Response.prototype.text
  • Response.prototype.json

详情可以查看 MDN 文档 https://developer.mozilla.org/en-US/docs/Web/API/Response

fetch('/api/ping').then(res => {  // true  console.log(res instanceof Response)  // 最常见的使用  return res.json()

  // 返回 Blob  // return res.blob()

  // 返回 ArrayBuffer  // return res.arrayBuffer()})

另外,万能的 Response API 既可以可以使用 TypedArrayBlobText 作为输入,又可以使用它们作为输出。

「这意味着关于这三种数据类型的转换完全可以通过 Response」

xhr

「xhr 可以设置 responseType 接收合适的数据类型」

const request = new XMLHttpRequest()request.responseType = 'arraybuffer'request.responseType = 'blob'

File

本地文件可以通过 input[type=file] 来上传文件。

<input type="file" id="input">

当上传成功后,可以通过 document.getElementById('input').files[0] 获取到上传的文件,即一个 File 对象,它是 Blob 的子类,可以通过 FileReader 或者 Response 获取文件内容。

数据输出

或者叫数据展示或者下载,数据经二进制处理后可以由 url 表示,然后通过 image, video 等元素引用或者直接下载。

Data URL

Data URL 即 Data As URL。所以, 「如果资源过大,地址便会很长。」 使用以下形式表示。

data:[][;base64],

先来一个 hello, world。把以下地址粘入地址栏,会访问到 hello, world

data:text/html,

Hello%2C%20World!


Base64 编码与解码

Base64 使用大小写字母,数字,+ 和 / 64 个字符来编码数据,所以称为 Base64。经编码后,文本体积会变大 1/3

在浏览器中,可以使用 atob 和 btoa 编码解码数据。

// aGVsbG8=btoa('hello')

Object URL

可以使用浏览器新的 API URL 对象生成一个地址来表示 Blob 数据。

// 粘贴生成的地址,可以访问到 hello, world// blob:http://host/27254c37-db7a-4f2f-8861-0cf9aec89a64URL.createObjectURL(new Blob('hello, world'.split('')))

下载

data:application/octet-stream;base64,5bGx5pyI

资源的下载可以利用 FileSaver[1] 。

这里也简单写一个函数,用来下载一个链接

function download (url, name) {  const a = document.createElement('a')  a.download = name  a.rel = 'noopener'  a.href = url  // 触发模拟点击  a.dispatchEvent(new MouseEvent('click'))  // 或者 a.click(}

二进制数据转换

二进制数据转换

以上是二进制数据间的转换图,有一些转换可以直接通过 API,有些则需要代码,以下贴几种常见转换的代码

String to TypedArray

根据上图,由字符串到 TypedArray 的转换,可以通过 「String -> Blob -> ArrayBuffer -> TypedArray」 的途径。

关于代码中的函数 readBlob 可以回翻环节 数据类型 - Blob[2]

const name = '山月'const blob = new Blob(name.split(''))

readBlob(blob, 'ArrayBuffer').then(buffer => new Uint8Array(buffer))

也可以通过 Response API 直接转换 「String -> ArrayBuffer -> TypedArray」

const name = '山月'

new Response(name).arrayBuffer(buffer => new Uint8Array(buffer))

这上边两种方法都是直接通过 API 来转化,如果你更像了解如何手动转换一个字符串和二进制的 TypedArray

String to TypedArray 2

使用 enodeURIComponent 把字符串转化为 utf8,再进行构造 TypedArray。

function stringToTypedArray(s) {  const str = encodeURIComponent(s)  const binstr = str.replace(/%([0-9A-F]{2})/g, (_, p1) => {    return String.fromCharCode('0x' + p1)  })  return new Uint8Array(binstr.split('').map(x => x.charCodeAt(0)))}

实践

1. 如何上传本地图片并在网页上展示

由以上整理的转换图得出途径

本地上传图片 -> Blob -> Object URL

2. 如何拼接两个音频文件

由以上整理的转换图得出途径

fetch请求音频资源 -> ArrayBuffer -> TypedArray -> 拼接成一个 TypedArray -> ArrayBuffer -> Blob -> Object URL

3. 如何把 json 数据转化为 demo.json 并下载文件

json 视为字符串,由以上整理的转换图得出途径

Text -> DataURL

除了使用 DataURL,还可以转化为 Object URL 进行下载。关于下载的函数 download,可以参考以上环节 数据输出-下载[3]

Text -> Blob -> Object URL

可以把以下代码直接粘贴到控制台下载文件

const json = {  a: 3,  b: 4,  c: 5}const str = JSON.stringify(json, null, 2)

// 方案一:Text -> DataURLconst dataUrl = `data:,${str}`download(dataUrl, 'demo.json')

// 方案二:Text -> Blob -> ObjectURLconst url = URL.createObjectURL(new Blob(str.split('')))download(url, 'demo1.json')

- EOF -

推荐阅读  点击标题可跳转

1、面试官:说说你对 options 请求的理解

2、你不知道的 Blob

3、了不起的 tsconfig.json 指南

觉得本文对你有帮助?请分享给更多人

关注「前端大全」加星标,提升前端技能

好文章,我在看❤️

-32767转化为二进制_谁说前端不需要懂二进制相关推荐

  1. c语言二进制转化为十进制_将十进制转换为C中的二进制

    c语言二进制转化为十进制 Here you will get program to convert decimal to binary in C. 在这里,您将获得将C中的十进制转换为二进制的程序. ...

  2. 编码 data text html c,谁说前端不需要懂二进制

    作者:全栈成长之路 公号 / 山月行 作为一名前端,在工作中也会遇到很多有关二进制处理的需求,如 EXCEL 表格的导出,PDF 的生成,多个文件的打包,音频的处理. 从前后端整体上来说前端代表 UI ...

  3. sql server代理无法启动_谁说前端不需要懂Nginx反向代理与负载均衡

    作者 | chenhongdong 链接 | https://juejin.im/post/5b01336af265da0b8a67e5c9 学到老活到老 前端圈一直很新,一直要不停的学习,而且在进入 ...

  4. python将十进制转为二进制_如何用Python将十进制数字转为二进制,以及将二进制转为十六进制?...

    匿名用户 1级 2017-11-28 回答 #首先说明一点,python有现成的函数可以干这个,只不过这个位数不会按照你想要的位数输出而已 #这些函数是 bin(), hex(), oct(),这些函 ...

  5. js图片转二进制流_为了安全问题后台返回前端得文件为二进制得流,我们该如何处理这些流文件...

    1遇到问题得场景:本来后台返给前端得图片,音频,视频等文件前端直接就能访问到!可是为了安全前端要在次请求这个路径而且还要加进去一个请求头.请求成功后后台返回你二进制得流!然后前端在解析这个二进制得流才 ...

  6. python中二进制转化为十进制_将二进制、八进制、十六进制转换为十进制

    学习视频 9节课征服「字符编码」-1-字符.字符集.字符编号与字符编码(基础课)-周华健的在线视频教程​edu.csdn.net 二进制.八进制和十六进制向十进制转换都非常容易,就是"按权相 ...

  7. python递归十进制转化二进制_什么是递归?用十进制转二进制的Python函数示例说明...

    先上用Python写的十进制转二进制的函数代码: def Dec2Bin(dec): result = '' if dec: result = Dec2Bin(dec//2) return resul ...

  8. 使用nginx负载均衡的webservice wsdl访问不到_谁说前端不用懂,Nginx 反向代理与负载均衡(超实用)...

    谁说前端不需要懂-Nginx反向代理与负载均衡 学到老活到老 前端圈一直很新,一直要不停的学习,而且在进入大厂的路上,还要求熟悉一门后台语言等等.用一句别人开玩笑的话来说,java十年前的技术现在还能 ...

  9. http 二进制_图解 HTTP 的前世今生!

    今天一起来研究HTTP协议的一些事情吧,聊一聊HTTP协议的前世今生. 乘风破浪前往知识的海洋吧,要开船了! 1. Http协议各版本的对比 Http超文本传输协议同空气一般,感触不到它的存在但是又无 ...

最新文章

  1. 【牛腩新闻发布系统】开始后端02
  2. date(w) 输出后对应的周几不对的问题
  3. 【PAT】B1070 结绳(25 分)
  4. 调用exe文件(一般处理登陆安全窗口)+睡眠等待(--------------------)
  5. 论文浅尝 | 利用问题生成提升知识图谱问答
  6. 离线安装 Pytorch 1.2.0 torchvision 0.3.0
  7. GNN 模型在生物化学和医疗健康中的典型应用
  8. MySQL 数据库优化设计
  9. 用C#写的汉语转拼音缩写的例子
  10. 【css练习】斑马线表格,美人尖,断线下划线
  11. 微软:推开窗户,我看到了云
  12. Go WebSocket开发与测试实践【gorilla/websocket】
  13. [洛谷P5068][Ynoi2015]我回来了
  14. atitit knowmng知识管理 索引part2
  15. python如何转换数据集_将数据集转换为HDF5数据
  16. JAVA_SE实现桌面化功能
  17. 2020年980计算机综合,2022年华北水利水电大学980计算机学科专业综合考研复习资料...
  18. 学习笔记之MIB相关
  19. 软件测试是干什么的 发展前景怎样?
  20. Python网络爬虫数据采集实战:Scrapy框架爬取QQ音乐存入MongoDB

热门文章

  1. python 知乎 合并 pdf_32.使用selenium爬取知乎,并实现多页保存为一个PDF文件
  2. css 倒三角_改善CSS的10种最佳做法,帮助你从样式中获得最大的收益。
  3. docker打包镜像(实用版)
  4. tensorflow精进之路(二十)——使用slim模型库训练自己的数据
  5. 【VS】项目属性配置(中)
  6. 一、计算二进制中1的个数
  7. 大数据系列3-第一章-大数据概论
  8. CImage实现双缓冲最近邻插值
  9. linux没有找到可用磁盘,在Linux上,有没有一种更像python的方法来获取可用磁盘设备名的列表?...
  10. matplotlib的一些代码