二进制流图片转 base64 或 blob 地址

发布于 2024-07-03 21:50:21 字数 4655 浏览 14 评论 0

前不久做了一个在前端展示小程序二维码的需求,怎料后台给出的接口并没有返回图片 url 地址,而是直接以二进制流的形式返回了一张图片。

base64 编码

我们知道 img 标签的 src 属性通常接收的值是一个路径地址,既然没有路径那我们就考虑另外一种方法,即 base64 编码数据显示图片。

来分析一下我们要做到把二进制流转换成 base64 编码都需要做哪些事情:

一般情况下后台返回的响应数据类型是 json,现在我们需要通过 responseType:arraybuffer 指定二进制流对应的响应类型 arraybuffer

ArrayBuffer 本质上是类型化数组,它作为内存区域,可以存放多种类型的数据。但 ArrayBuffer 不能直接操作,而是要通过类型数组对象或 DataView 对象来操作,它们会将缓冲区中的数据表示为特定的格式,并通过这些格式来读写缓冲区的内容。这些类型数组对象我们称为“视图”。有以下类型:

Int8Array:8 位有符号整数,长度 1 个字节。
Uint8Array:8 位无符号整数,长度 1 个字节。
Int16Array:16 位有符号整数,长度 2 个字节。
Uint16Array:16 位无符号整数,长度 2 个字节。
Int32Array:32 位有符号整数,长度 4 个字节。
Uint32Array:32 位无符号整数,长度 4 个字节。
Float32Array:32 位浮点数,长度 4 个字节。
Float64Array:64 位浮点数,长度 8 个字节。

// 创建一个指向后台返回的二进制流的 Uint8 视图
new Uint8Array(response.data)

这里我们在二进制流上建立一个 Uint8 的视图来对接收到的二进制流进行操作,将其转化为字符串。这就到了 String.fromCharCode() 方法登场的时间了。

fromCharCode() 可接受一个指定的 Unicode 值,然后返回一个字符串。而其实上面得到的视图是一组字节数组,和一般的数组基本无异。之前有看到别人在处理视图转成字符串用了 reduce() 方法:

new Uint8Array(response.data).reduce((data, byte) => data + String.fromCharCode(byte), '')

利用了 reduce() 方法累加的作用将视图中的值一个一个的转成字符串然后拼接起来。 reduce() 方法接收一个函数作为累加器,数组中的每个值(从左到右)开始缩减,最终计算为一个值。
array.reduce(function(total, currentValue, currentIndex, arr), initialValue)

参数描述
total必需。初始值, 或者计算结束后的返回值。
currentValue必需。当前元素
currentIndex可选。当前元素的索引
arr可选。当前元素所属的数组对象
initialValue可选。传递给函数的初始值

但其实 fromCharCode() 可以同时接受多个 Unicode 值,利用 ES6 的 ... 扩展运算符可以将上面获得的类型化数组作为参数序列一次性将它们转化为字符串

String.fromCharCode(...new Uint8Array(response.data))

这样是不是优雅多了,现在我们已经得到了由初始的二进制流转化成的字符串,最后只要通过 btoa() 这个方法将字符串转化为 base64 编码的字符串再拼接在 data:image/jpeg;base64, 后面就可以放入 src 属性中使用了。

最终的完整处理方式如下:

let imgUrl = 'data:image/jpeg;base64,' + btoa(String.fromCharCode(...new Uint8Array(response.data)))

blob 对象

转来转去我们总算是如愿的得到了我们想要的结果,但是在隐约中仿佛想起见过 blob:*** 这样的图片地址,研究了一下不禁大拍脑门,之前的实现过程真的是绕了好大的弯,其实只要简简单单的两个语句就可以轻松实现这个需求:

var blob = new Blob([response.data], {type: "image/jpeg"});
var imUrl = URL.createObjectURL(blob);

Blob 对象表示一个不可变、原始数据的类文件对象,是一个可以存储二进制文件的容器。

var blob = new Blob( array, options );
  • array 是一个由 ArrayBuffer,ArrayBufferView,Blob,DOMString 等对象构成的 Array,或者其他类似对象的混合体,它将会被放进 Blob
  • options 提供了一个 type 属性,代表了将会被放入到 blob 中的数组内容的 MIME 类型,默认为 ""

后台给我们返回的数据刚好是 ArrayBuffer ,不用任何操作直接放进 Blob 对象,并指定图片 MIME 类型,我们就创建了一个存放这张图片的 Blob 对象,再通过 URL.createObjectURL() 方法创建一个指向 Blob 对象的 URL,就可以直接拿来用了。

结语

这一次的探究找寻到的两种解决方案虽然难易程度相差比较大,但是过程中学习到的知识点还是很多的。可能如果先知道了第二种方法也就不会花时间去了解第一种方法的实现原理了。所以,相信过程吧,总不会是白忙活的。

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。
列表为空,暂无数据

关于作者

后eg是否自

暂无简介

0 文章
0 评论
22 人气
更多

推荐作者

内心激荡

文章 0 评论 0

JSmiles

文章 0 评论 0

左秋

文章 0 评论 0

迪街小绵羊

文章 0 评论 0

瞳孔里扚悲伤

文章 0 评论 0

    我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
    原文