关于二进制的一点小思考

栏目: JavaScript · 发布时间: 5年前

内容简介:在这次的公众号项目中,需要一个用户的小程序二维码,一开始想的是实时生成小程序二维码,后台问我行不行,隐约记得微信好像确实提供了这个功能,就答应下来了。一开始以为只需要access_tojen我就可以自己生成了,然而我好像忽略了getWXACodeUnlimit 文档说的是:如果调用成功,会直接返回图片二进制内容,如果请求失败,会返回 JSON 格式的数据。

在这次的公众号项目中,需要一个用户的小程序二维码,一开始想的是实时生成小程序二维码,后台问我行不行,隐约记得微信好像确实提供了这个功能,就答应下来了。一开始以为只需要access_tojen我就可以自己生成了,然而我好像忽略了 跨域 这件事。没办法,看来还是得 后台中转一下 了。因为后台暂时没空,我就要了appid和secret先自己用node试试效果。

getWXACodeUnlimit 文档说的是:

如果调用成功,会直接返回图片二进制内容,如果请求失败,会返回 JSON 格式的数据。

2. 问题来了

二进制内容是什么?ArrayBuffer还是Blob?都试试吧。

隐约记得,XHR2可以从服务器获取其他格式的数据了。

数据类型
'' DOMString (这个是默认类型)
arraybuffer ArrayBuffer对象
blob Blob对象
document Document对象
json JavaScript object, parsed from a JSON string returned by the server
text DOMString

我一开始还以为如果设置了responseType为Blob的话,返回的是字符串。当时可真的是一顿操作猛如虎,一看结果250。

关于二进制的一点小思考

其实只要查看一下 响应数据的constructor 属性就知道返回数据是什么类型的了,回想起来真的是好尴尬,竟然连这么基础的知识都忘了。

关于二进制的一点小思考

废话不多说,下面说我的解决方案吧。

3. 使用Blob作为图片的src

在这里想出来3种办法(_blob为ajax请求得到的Blob对象):

3.1 使用 window.URL 的方法

var src = window.URL.createObjectURL(blob);
document.querySelector("#img").setAttribute("src", src)

// createObjectURL创建的数据不会自行释放,所以无用的时候还得调用如下方法进行手动释放
window.URL.revokeObjectURL(src)
复制代码

3.2 使用 FileReader 的方法

var reader = new FileReader();
reader.onload = (e) => {
  document.querySelector("#img").setAttribute("src", reader.result)
}
reader.readAsDataURL(_blob);
复制代码

3.3 直接将接口地址设置为src的值

// 假设接口的地址是 http://test.com/index/getWxImg

// html
<img src="http://test.com/index/getWxImg" alt="微信小程序二维码" />
复制代码

这就相当于在浏览器地址栏直接通过url访问该图片了,他会自动根据响应头的 Content-Type响应数据 进行展示。当然了,这种方式只限于 get 请求,如果接口的请求方式只能是 post, 就只能用前两种方式了。

这次可真是闹了一个大乌龙,痛定思痛,我决定对 ArrayBufferBlob 进行一个较为深入的理解。

4. 名词解释

4.1 ArrayBuffer(二进制数组)

二进制数组(ArrayBuffer对象、TypedArray视图和DataView视图)是JavaScript操作二进制数据的一个接口。 这个接口的原始设计目的,与WebGL项目有关。所谓WebGL,就是指浏览器与显卡之间的通信接口,为了满足JavaScript与显卡之间大量的、实时的数据交换,它们之间的数据通信必须是二进制的,而不能是传统的文本格式。文本格式传递一个32位整数,两端的JavaScript脚本与显卡都要进行格式转化,将非常耗时。这时要是存在一种机制,可以像 C语言 那样,直接操作字节,将4个字节的32位整数,以二进制形式原封不动地送入显卡,脚本的性能就会大幅提升。

4.2 Blob(二进制数据)

Blob 对象表示一个不可变、原始数据的类文件对象。Blob 表示的不一定是JavaScript原生格式的数据。File 接口基于Blob,继承了 blob 的功能并将其扩展使其支持用户系统上的文件。

Blob的构造函数为 Blob(blobParts[, options])。第一个参数必须为数组,可以是字符串数组,可以是二进制数组。options是一个对象,主要通过设置 type 值来指定文件的 content-type。

简单来说,可以直接把ArrayBuffer当成二进制数组,而把Blob当成是二进制数据。(这么说没错吧?如果理解的不对,欢迎指正。)

5. Blob与其他数据类型的转换

5.1 base64转为Blob

function dataURL2Blob(dataurl) {
  var arr = dataurl.split(','), mime = arr[0].match(/:(.*?);/)[1],
      bstr = atob(arr[1]), n = bstr.length, u8arr = new Uint8Array(n);
  while (n--) {
      u8arr[n] = bstr.charCodeAt(n);
  }
  return new Blob([u8arr], { type: mime });
}
复制代码

5.2 字符串转为Blob

function plain2Blob(text, type) {
  return new Blob([text], { type: 'text/plain' });
}
复制代码

5.3 ArrayBuffer转为Blob

function buffer2Blob(_buffer, type) {
  return new Blob([_buffer], { type: 'application/octet-stream' });
}
复制代码

5.4 Blob转为其他类型

从Blob中读取内容的唯一方法是使用 FileReader

var _blob = new Blob([]); //假设它是一个有效的Blob对象
var reader = new FileReader();
reader.onload = (e) => {
  console.log(reader.result)
}
复制代码
reader.readAsDataURL(_blob);
reader.readAsText(_blob);
reader.readAsArrayBuffer(_blob);

6. 利用Blob下载文件

6.1 下载函数

// @params content: String
// @params type: String
// @params filename: String
function downloadFile(content, type = 'text', filename) {
  var textBlob;
  if (type === 'img') {
    textBlob = dataURL2Blob(content);
    if (!filename) {
      throw new Error('type为img时, filename 文件名参数必传');
    }
  } else {
    textBlob = plain2Blob(content, type);
    filename = filename || generateFilename(type);
  }

  var a = document.createElement("a"),
      href = URL.createObjectURL(textBlob);
  a.href = href;
  a.download = filename;
  document.body.appendChild(a);
  a.click();

  document.body.removeChild(a);
  URL.revokeObjectURL(href);
}

function dataURL2Blob(dataurl) {
  var arr = dataurl.split(','), mime = arr[0].match(/:(.*?);/)[1],
      bstr = atob(arr[1]), n = bstr.length, u8arr = new Uint8Array(n);
  while (n--) {
      u8arr[n] = bstr.charCodeAt(n);
  }
  return new Blob([u8arr], { type: mime });
}

function plain2Blob(text, type) {
  var fileTypes = {
    text: 'text/plain',
    svg: 'image/svg+xml',
  }

  return new Blob([text], { type: fileTypes[type] || 'application/octet-stream' })
}

function generateFilename(type) {
  var prefixs = {
    text: 'txt',
    svg: 'svg',
  }

  return '1.' + (prefixs[type] || '.txt')
}
复制代码

6.2 测试

// 下载txt文件
downloadFile(`测试\r\n第二行`, 'text',)

// 下载svg
downloadFile(`<svg version="1.1" id="tuceng_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
width="80px" height="36px" viewBox="0 0 80 36" enable-background="new 0 0 80 36" xml:space="preserve">
<rect y="34.129" fill="#009944" width="36" height="2"/>
</svg>`, 'svg', '1.svg')

// 下载图片
var data = 'data:image/png;base64,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 Go 2br+qXapWBdpVldq1OXFXua/801sZIIQBQhgghAFCGCC+spp01be1anKD2OLLJrcH9l3ngbvqrAwQwgAhDBDCACEMEDdnup3dAPWNm61W7rXxTLeavvneZzuRVqgmwZ8RBghhgBAGCGGAWKomTZoczlxra+nrg1q8eO12u76is+W+1sP7rAwQwgAhDBDCACEMEDfVJPh/sjJACAOEMEAIA4QwQAgDxD+aYuUyl4qrbgAAAABJRU5ErkJggg==';
downloadFile(data, 'img', '1.png')
复制代码

6.3 下载函数说明

目前只支持文本文件,svg,图片三种格式。

7 总结

Blob的作用还是蛮大的,在一定程度上可以在前端直接生成文件从而进行 上传或者下载

File 也是 继承自 Blob, 所以生成的 图片Blob 也是可以直接通过 ajax 上传 OSS 之类的进行存储。之前有一个项目其中一部分是 在线PPT,我就是用 Blob 上传 PPT的首图 到 OSS 的。


以上所述就是小编给大家介绍的《关于二进制的一点小思考》,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对 码农网 的支持!

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

阿里巴巴Java开发手册

阿里巴巴Java开发手册

杨冠宝 / 电子工业出版社 / 2018-1 / 35

《阿里巴巴Java开发手册》的愿景是码出高效,码出质量。它结合作者的开发经验和架构历程,提炼阿里巴巴集团技术团队的集体编程经验和软件设计智慧,浓缩成为立体的编程规范和最佳实践。众所周知,现代软件行业的高速发展对开发者的综合素质要求越来越高,因为不仅是编程相关的知识点,其他维度的知识点也会影响软件的最终交付质量,比如,数据库的表结构和索引设计缺陷可能带来软件的架构缺陷或性能风险;单元测试的失位导致集......一起来看看 《阿里巴巴Java开发手册》 这本书的介绍吧!

HTML 编码/解码
HTML 编码/解码

HTML 编码/解码

正则表达式在线测试
正则表达式在线测试

正则表达式在线测试

RGB HSV 转换
RGB HSV 转换

RGB HSV 互转工具