js如何实现小程序wx.arrayBufferToBase64方法实例

 更新时间:2022年3月5日 16:46  点击:854 作者:定栓

前言

在小程序开发中,需要将接口请求获得的arrayBuffer数据,转换为base64格式数据,进行图片的显示。

微信小程序提供了wx.arrayBufferToBase64方法,但很不幸,这个方法在基础库版本 2.4.0 起已废弃,已不推荐使用。

虽然目前即使小程序基础库版本为2.22.0,也能正常使用。但是不确定未来哪天,在更新的基础库中,该方法被删除。这样就会带来项目上的隐患。

所以需要自己去实现arrayBuffer转为base64这一过程。

探索失败的过程

  • new FileReader()在小程序中无法进行使用。无法使用new FileReader()实例中的readAsDataURL方法将数据转为base64。如果不熟悉该方法,可以查看FileReader介绍
  • URL.createObjectURL在小程序中无法使用。无法使用该方法将数据转为在内存中的地址,进而能被image标签进行引用。如果不熟悉该方法,可以查看URL.createObjectURL讲解
  • window.btoa在小程序中无法使用。无法将文本直接转为base64格式。

好了,条条大路都被阻断了。那就该自己铺路搭桥了。

卡壳的arrayBuffer转base64

问题的起始条件有arrayBuffer数据,期望结果是最终形成base64格式数据。那开始进行求解。

首先我们得来说说arrayBuffer这回事。

在JavaScript中,有一个很常用的引用数据类型Array,你可以在里面放字符串、数字、对象、布尔值等等等等。它存放在堆中,可以自由增减。

ArrayBuffer 对象用来表示通用的、固定长度的原始二进制数据缓冲区。它是一个字节数组,通常在其他语言中称为“byte array”。它的诞生就是为了解决一个问题:操作二进制数据。

只由0和1组成的二进制数据往往是非常巨大的,上千个字节可以说司空见惯,传统的Array这时候处理起二进制数据起来就显得非常低效,所以ArrayBuffer出现了,它作为一块专用的内存区域存放在栈中,取数据非常快。

我们现在通过new ArrayBuffer(10)初始化一个buffer实例,看看会得到什么。

let buffer = new ArrayBuffer(10);
console.log(buffer);

// 在控制台上显示如下
ArrayBuffer(10)
byteLength: 10
[[Prototype]]: ArrayBuffer
[[Int8Array]]: Int8Array(10)
[[Uint8Array]]: Uint8Array(10)
[[Int16Array]]: Int16Array(5)
[[ArrayBufferByteLength]]: 10
[[ArrayBufferData]]: 1367

可以看到在ArrayBuffer中,主要存放了几个“视图”,Int8Array表示8位有符号整数数组,Int16Array表示16位有符号整数数组,Uint8Array则表示8位无符号整数数组。

当然,如果比如说我们想取出Int8Array这个数组来,是不能直接通过buffer.Int8Array来取的。这是因为ArrayBuffer不能直接通过下标去读写,我们需要把它转成一个类型化数组(TypedArray)。

你不能直接操作 ArrayBuffer 的内容,而是要通过类型数组对象或 DataView 对象来操作,它们会将缓冲区中的数据表示为特定的格式,并通过这些格式来读写缓冲区的内容。

const myTypedArray = new Uint8Array(buffer)

转化完之后,我们我们不仅可以通过下标去对类型化数组进行索引,也可以获取其length,当然TypedArray仍与普通的Array存在细微的区别,那就是假设我们用超出边界的索引语法去获取数组元素时,TypedArray并不会去原型链中进行查找。

现在我们已经拿到了这个类型化数组,是时候把它转成普通字符串了。看看String.fromCharCode这个函数,它接受的参数为一堆代码单元序列,输出一个普通字符串。而我们刚刚得到的类型化数组,里面存放的正是代码单元。

const str = String.fromCharCode(...myTypedArray)

这里我们用拓展运算符...把类型数组的代码单元解出来,一次性转完,得到一个普通的字符串。

最后,我们需要借助一个window对象的方法,也就是btoa方法,它的作用是:把一个普通字符串编码成base-64格式的字符串。

上面看似很好,但是在最后一步,btoa,在小程序中是没有该方法的去使用的。需要自己去实现btoa这个方法。

关键点btoa的实现

因为该函数,在浏览器中已经实现,所以更多使用在小程序及node环境中。所以总体以module.exports进行方法的输出,以require形式进行引入。

输出方法

module.exports = {
  btoa: ...,
  atob: ...
}

引入文件

const { btoa } =  require('./base64')

base64.js

var b64 = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/",
  a256 = '',
  r64 = [256],
  r256 = [256],
  i = 0;

var UTF8 = {

  /**
   * Encode multi-byte Unicode string into utf-8 multiple single-byte characters
   * (BMP / basic multilingual plane only)
   *
   * Chars in range U+0080 - U+07FF are encoded in 2 chars, U+0800 - U+FFFF in 3 chars
   *
   * @param {String} strUni Unicode string to be encoded as UTF-8
   * @returns {String} encoded string
   */
  encode: function (strUni) {
    // use regular expressions & String.replace callback function for better efficiency
    // than procedural approaches
    var strUtf = strUni.replace(/[\u0080-\u07ff]/g, // U+0080 - U+07FF => 2 bytes 110yyyyy, 10zzzzzz
      function (c) {
        var cc = c.charCodeAt(0);
        return String.fromCharCode(0xc0 | cc >> 6, 0x80 | cc & 0x3f);
      })
      .replace(/[\u0800-\uffff]/g, // U+0800 - U+FFFF => 3 bytes 1110xxxx, 10yyyyyy, 10zzzzzz
        function (c) {
          var cc = c.charCodeAt(0);
          return String.fromCharCode(0xe0 | cc >> 12, 0x80 | cc >> 6 & 0x3F, 0x80 | cc & 0x3f);
        });
    return strUtf;
  },

  /**
   * Decode utf-8 encoded string back into multi-byte Unicode characters
   *
   * @param {String} strUtf UTF-8 string to be decoded back to Unicode
   * @returns {String} decoded string
   */
  decode: function (strUtf) {
    // note: decode 3-byte chars first as decoded 2-byte strings could appear to be 3-byte char!
    var strUni = strUtf.replace(/[\u00e0-\u00ef][\u0080-\u00bf][\u0080-\u00bf]/g, // 3-byte chars
      function (c) { // (note parentheses for precence)
        var cc = ((c.charCodeAt(0) & 0x0f) << 12) | ((c.charCodeAt(1) & 0x3f) << 6) | (c.charCodeAt(2) & 0x3f);
        return String.fromCharCode(cc);
      })
      .replace(/[\u00c0-\u00df][\u0080-\u00bf]/g, // 2-byte chars
        function (c) { // (note parentheses for precence)
          var cc = (c.charCodeAt(0) & 0x1f) << 6 | c.charCodeAt(1) & 0x3f;
          return String.fromCharCode(cc);
        });
    return strUni;
  }
};

while (i < 256) {
  var c = String.fromCharCode(i);
  a256 += c;
  r256[i] = i;
  r64[i] = b64.indexOf(c);
  ++i;
}

function code(s, discard, alpha, beta, w1, w2) {
  s = String(s);
  var buffer = 0,
    i = 0,
    length = s.length,
    result = '',
    bitsInBuffer = 0;

  while (i < length) {
    var c = s.charCodeAt(i);
    c = c < 256 ? alpha[c] : -1;

    buffer = (buffer << w1) + c;
    bitsInBuffer += w1;

    while (bitsInBuffer >= w2) {
      bitsInBuffer -= w2;
      var tmp = buffer >> bitsInBuffer;
      result += beta.charAt(tmp);
      buffer ^= tmp << bitsInBuffer;
    }
    ++i;
  }
  if (!discard && bitsInBuffer > 0) result += beta.charAt(buffer << (w2 - bitsInBuffer));
  return result;
}

var Plugin = function (dir, input, encode) {
  return input ? Plugin[dir](input, encode) : dir ? null : this;
};

Plugin.btoa = Plugin.encode = function (plain, utf8encode) {
  plain = Plugin.raw === false || Plugin.utf8encode || utf8encode ? UTF8.encode(plain) : plain;
  plain = code(plain, false, r256, b64, 8, 6);
  return plain + '===='.slice((plain.length % 4) || 4);
};

Plugin.atob = Plugin.decode = function (coded, utf8decode) {
  coded = coded.replace(/[^A-Za-z0-9\+\/\=]/g, "");
  coded = String(coded).split('=');
  var i = coded.length;
  do {
    --i;
    coded[i] = code(coded[i], true, r64, a256, 6, 8);
  } while (i > 0);
  coded = coded.join('');
  return Plugin.raw === false || Plugin.utf8decode || utf8decode ? UTF8.decode(coded) : coded;
};
module.exports = {
  btoa: Plugin.btoa,
  atob: Plugin.atob
}

修成正果

有时候后台把图片资源通过arrayBuffer传给前端,这时候为了能正常显示,我们还需要在转化的base64字符串前面拼接上data:image/jpeg;base64,

所以我们整理一下,可以得出这样一个函数:

const { btoa } =  require('./base64')
const arrayBufferToBase64Img = (buffer) => {
  const str = String.fromCharCode(...new Uint8Array(buffer));
  return `data:image/jpeg;base64,${btoa(str)}`;
}

整个流程如下:

得到一个ArrayBuffer ---> 转成类型化数组以正常读取(Uint8Array) --> 转成普通字符串(String.fromCharCode) --> 转成base64字符串(btoa)

总结

到此这篇关于js如何实现小程序wx.arrayBufferToBase64方法实例的文章就介绍到这了,更多相关js实现小程序wx.arrayBufferToBase64内容请搜索猪先飞以前的文章或继续浏览下面的相关文章希望大家以后多多支持猪先飞!

原文出处:https://juejin.cn/post/7070893561121603614

[!--infotagslink--]

相关文章

  • JavaScript判断浏览器及其版本信息

    本篇文章主要分享了通过window.navigator来判断浏览器及其版本信息的实例代码。具有一定的参考价值,下面跟着小编一起来看下吧...2017-01-23
  • js实现浏览器打印功能的示例代码

    这篇文章主要介绍了js如何实现浏览器打印功能,文中示例代码非常详细,帮助大家更好的理解和学习,感兴趣的朋友可以了解下...2020-07-15
  • 微信小程序 页面传值详解

    这篇文章主要介绍了微信小程序 页面传值详解的相关资料,需要的朋友可以参考下...2017-03-13
  • Nest.js参数校验和自定义返回数据格式详解

    这篇文章主要给大家介绍了关于Nest.js参数校验和自定义返回数据格式的相关资料,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧...2021-03-28
  • 利用JS实现点击按钮后图片自动切换的简单方法

    下面小编就为大家带来一篇利用JS实现点击按钮后图片自动切换的简单方法。小编觉得挺不错的,现在就分享给大家,也给大家做个参考。一起跟随小编过来看看吧...2016-10-25
  • 详解前端安全之JavaScript防http劫持与XSS

    作为前端,一直以来都知道HTTP劫持与XSS跨站脚本、CSRF跨站请求伪造。防御这些劫持最好的方法是从后端入手,前端能做的太少。而且由于源码的暴露,攻击者很容易绕过防御手段。但这不代表我们去了解这块的相关知识是没意义的,本文的许多方法,用在其他方面也是大有作用。...2021-05-24
  • js+css实现回到顶部按钮(back to top)

    这篇文章主要为大家详细介绍了js+css实现回到顶部按钮back to top回到顶部按钮,感兴趣的小伙伴们可以参考一下...2016-03-03
  • JavaScript仿支付宝密码输入框

    那么今天我就用JavaScript代码来实现这个效果吧,那么首先介绍一下整个的思路,首先我们先将确定输入密码的位数,我的需求是5位,那么就用一个div标签包住5个input标签...2016-01-02
  • uniapp微信小程序:key失效的解决方法

    这篇文章主要介绍了uniapp微信小程序:key失效的解决方法,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧...2021-01-20
  • js实现上传图片及时预览

    这篇文章主要为大家详细介绍了js实现上传图片及时预览的相关资料,具有一定的参考价值,感兴趣的朋友可以参考一下...2016-05-09
  • js实现调用网络摄像头及常见错误处理

    这篇文章主要介绍了js实现调用网络摄像头及常见错误处理,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧...2021-03-07
  • JS实现随机生成验证码

    这篇文章主要为大家详细介绍了JS实现随机生成验证码,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下...2021-09-06
  • js组件SlotMachine实现图片切换效果制作抽奖系统

    这篇文章主要介绍了js组件SlotMachine实现图片切换效果制作抽奖系统的相关资料,需要的朋友可以参考下...2016-04-19
  • vue.js 表格分页ajax 异步加载数据

    Vue.js通过简洁的API提供高效的数据绑定和灵活的组件系统.这篇文章主要介绍了vue.js 表格分页ajax 异步加载数据的相关资料,需要的朋友可以参考下...2016-10-20
  • 基于JavaScript实现表单密码的隐藏和显示出来

    为了网站的安全性,很多朋友都把密码设的比较复杂,但是如何密码不能明显示,不知道输的是对是错,为了安全起见可以把密码显示的,那么基于js代码如何实现的呢?下面通过本文给大家介绍JavaScript实现表单密码的隐藏和显示,需要的朋友参考下...2016-03-03
  • js实现列表按字母排序

    这篇文章主要为大家详细介绍了js实现列表按字母排序,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下...2020-08-11
  • 基于JavaScript实现文字超出部分隐藏

    这篇文章主要介绍了基于JavaScript实现文字超出部分隐藏 的相关资料,需要的朋友可以参考下...2016-03-01
  • JS实现响应鼠标点击动画渐变弹出层效果代码

    这篇文章主要介绍了JS实现响应鼠标点击动画渐变弹出层效果代码,具有非常自然流畅的动画过度效果,涉及JavaScript针对鼠标事件的响应及页面元素样式的动态操作相关技巧,需要的朋友可以参考下...2016-03-28
  • 一个关于JS正则匹配的踩坑记录

    这篇文章主要给大家介绍了一个关于JS正则匹配的踩坑记录,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧...2021-04-13
  • PHP常用的小程序代码段

    本文实例讲述了PHP常用的小程序代码段。分享给大家供大家参考,具体如下:1.计算两个时间的相差几天$startdate=strtotime("2009-12-09");$enddate=strtotime("2009-12-05");上面的php时间日期函数strtotime已经把字符串...2015-11-24