如何用js實(shí)現(xiàn)小程序wx.arrayBufferToBase64

這篇文章主要介紹“如何用js實(shí)現(xiàn)小程序wx.arrayBufferToBase64”,在日常操作中,相信很多人在如何用js實(shí)現(xiàn)小程序wx.arrayBufferToBase64問題上存在疑惑,小編查閱了各式資料,整理出簡(jiǎn)單好用的操作方法,希望對(duì)大家解答”如何用js實(shí)現(xiàn)小程序wx.arrayBufferToBase64”的疑惑有所幫助!接下來,請(qǐng)跟著小編一起來學(xué)習(xí)吧!

站在用戶的角度思考問題,與客戶深入溝通,找到蘇尼特右網(wǎng)站設(shè)計(jì)與蘇尼特右網(wǎng)站推廣的解決方案,憑借多年的經(jīng)驗(yàn),讓設(shè)計(jì)與互聯(lián)網(wǎng)技術(shù)結(jié)合,創(chuàng)造個(gè)性化、用戶體驗(yàn)好的作品,建站類型包括:成都網(wǎng)站設(shè)計(jì)、成都網(wǎng)站制作、外貿(mào)網(wǎng)站建設(shè)、企業(yè)官網(wǎng)、英文網(wǎng)站、手機(jī)端網(wǎng)站、網(wǎng)站推廣、空間域名、雅安服務(wù)器托管、企業(yè)郵箱。業(yè)務(wù)覆蓋蘇尼特右地區(qū)。

探索失敗的過程

  • new FileReader()在小程序中無法進(jìn)行使用。無法使用new FileReader()實(shí)例中的readAsDataURL方法將數(shù)據(jù)轉(zhuǎn)為base64。如果不熟悉該方法,可以查看FileReader介紹

  • URL.createObjectURL在小程序中無法使用。無法使用該方法將數(shù)據(jù)轉(zhuǎn)為在內(nèi)存中的地址,進(jìn)而能被image標(biāo)簽進(jìn)行引用。如果不熟悉該方法,可以查看URL.createObjectURL講解

  • window.btoa在小程序中無法使用。無法將文本直接轉(zhuǎn)為base64格式。

好了,條條大路都被阻斷了。那就該自己鋪路搭橋了。

卡殼的arrayBuffer轉(zhuǎn)base64

問題的起始條件有arrayBuffer數(shù)據(jù),期望結(jié)果是最終形成base64格式數(shù)據(jù)。那開始進(jìn)行求解。

首先我們得來說說arrayBuffer這回事。

在JavaScript中,有一個(gè)很常用的引用數(shù)據(jù)類型Array,你可以在里面放字符串、數(shù)字、對(duì)象、布爾值等等等等。它存放在堆中,可以自由增減。

ArrayBuffer 對(duì)象用來表示通用的、固定長(zhǎng)度的原始二進(jìn)制數(shù)據(jù)緩沖區(qū)。它是一個(gè)字節(jié)數(shù)組,通常在其他語(yǔ)言中稱為“byte array”。它的誕生就是為了解決一個(gè)問題:操作二進(jìn)制數(shù)據(jù)。

只由0和1組成的二進(jìn)制數(shù)據(jù)往往是非常巨大的,上千個(gè)字節(jié)可以說司空見慣,傳統(tǒng)的Array這時(shí)候處理起二進(jìn)制數(shù)據(jù)起來就顯得非常低效,所以ArrayBuffer出現(xiàn)了,它作為一塊專用的內(nèi)存區(qū)域存放在棧中,取數(shù)據(jù)非???。

我們現(xiàn)在通過new ArrayBuffer(10)初始化一個(gè)buffer實(shí)例,看看會(huì)得到什么。

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

// 在控制臺(tái)上顯示如下
ArrayBuffer(10)
byteLength: 10
[[Prototype]]: ArrayBuffer
[[Int8Array]]: Int8Array(10)
[[Uint8Array]]: Uint8Array(10)
[[Int16Array]]: Int16Array(5)
[[ArrayBufferByteLength]]: 10
[[ArrayBufferData]]: 1367

可以看到在ArrayBuffer中,主要存放了幾個(gè)“視圖”,Int8Array表示8位有符號(hào)整數(shù)數(shù)組,Int16Array表示16位有符號(hào)整數(shù)數(shù)組,Uint8Array則表示8位無符號(hào)整數(shù)數(shù)組。

當(dāng)然,如果比如說我們想取出Int8Array這個(gè)數(shù)組來,是不能直接通過buffer.Int8Array來取的。這是因?yàn)锳rrayBuffer不能直接通過下標(biāo)去讀寫,我們需要把它轉(zhuǎn)成一個(gè)類型化數(shù)組(TypedArray)。

你不能直接操作 ArrayBuffer 的內(nèi)容,而是要通過類型數(shù)組對(duì)象或 DataView 對(duì)象來操作,它們會(huì)將緩沖區(qū)中的數(shù)據(jù)表示為特定的格式,并通過這些格式來讀寫緩沖區(qū)的內(nèi)容。

const myTypedArray = new Uint8Array(buffer)

轉(zhuǎn)化完之后,我們我們不僅可以通過下標(biāo)去對(duì)類型化數(shù)組進(jìn)行索引,也可以獲取其length,當(dāng)然TypedArray仍與普通的Array存在細(xì)微的區(qū)別,那就是假設(shè)我們用超出邊界的索引語(yǔ)法去獲取數(shù)組元素時(shí),TypedArray并不會(huì)去原型鏈中進(jìn)行查找。

現(xiàn)在我們已經(jīng)拿到了這個(gè)類型化數(shù)組,是時(shí)候把它轉(zhuǎn)成普通字符串了??纯碨tring.fromCharCode這個(gè)函數(shù),它接受的參數(shù)為一堆代碼單元序列,輸出一個(gè)普通字符串。而我們剛剛得到的類型化數(shù)組,里面存放的正是代碼單元。

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

這里我們用拓展運(yùn)算符...把類型數(shù)組的代碼單元解出來,一次性轉(zhuǎn)完,得到一個(gè)普通的字符串。

最后,我們需要借助一個(gè)window對(duì)象的方法,也就是btoa方法,它的作用是:把一個(gè)普通字符串編碼成base-64格式的字符串。

上面看似很好,但是在最后一步,btoa,在小程序中是沒有該方法的去使用的。需要自己去實(shí)現(xiàn)btoa這個(gè)方法。

關(guān)鍵點(diǎn)btoa的實(shí)現(xiàn)

因?yàn)樵摵瘮?shù),在瀏覽器中已經(jīng)實(shí)現(xiàn),所以更多使用在小程序及node環(huán)境中。所以總體以module.exports進(jìn)行方法的輸出,以require形式進(jìn)行引入。

輸出方法

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
}

修成正果

有時(shí)候后臺(tái)把圖片資源通過arrayBuffer傳給前端,這時(shí)候?yàn)榱四苷o@示,我們還需要在轉(zhuǎn)化的base64字符串前面拼接上data:image/jpeg;base64,

所以我們整理一下,可以得出這樣一個(gè)函數(shù):

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

整個(gè)流程如下:

得到一個(gè)ArrayBuffer ---> 轉(zhuǎn)成類型化數(shù)組以正常讀取(Uint8Array) --> 轉(zhuǎn)成普通字符串(String.fromCharCode) --> 轉(zhuǎn)成base64字符串(btoa)

到此,關(guān)于“如何用js實(shí)現(xiàn)小程序wx.arrayBufferToBase64”的學(xué)習(xí)就結(jié)束了,希望能夠解決大家的疑惑。理論與實(shí)踐的搭配能更好的幫助大家學(xué)習(xí),快去試試吧!若想繼續(xù)學(xué)習(xí)更多相關(guān)知識(shí),請(qǐng)繼續(xù)關(guān)注創(chuàng)新互聯(lián)網(wǎng)站,小編會(huì)繼續(xù)努力為大家?guī)砀鄬?shí)用的文章!

網(wǎng)站欄目:如何用js實(shí)現(xiàn)小程序wx.arrayBufferToBase64
當(dāng)前地址:http://muchs.cn/article14/iegege.html

成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供網(wǎng)站維護(hù)、App開發(fā)、軟件開發(fā)移動(dòng)網(wǎng)站建設(shè)、自適應(yīng)網(wǎng)站ChatGPT

廣告

聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請(qǐng)盡快告知,我們將會(huì)在第一時(shí)間刪除。文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如需處理請(qǐng)聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時(shí)需注明來源: 創(chuàng)新互聯(lián)

成都定制網(wǎng)站網(wǎng)頁(yè)設(shè)計(jì)