将base64字符串转换为ArrayBuffer

时间:2014-02-15 12:05:49

标签: javascript base64 arraybuffer

我需要将base64编码字符串转换为ArrayBuffer。 base64字符串是用户输入,它们将从电子邮件中复制和粘贴,因此在加载页面时它们不存在。 我希望在javascript中执行此操作,如果可能的话,不要对服务器进行ajax调用。

我发现这些链接很有趣,但他们没有帮助我:

ArrayBuffer to base64 encoded string

这是相反的转换,从ArrayBuffer到base64,而不是相反的转换

http://jsperf.com/json-vs-base64/2

这看起来不错,但我无法弄清楚如何使用代码。

是否有简单的(可能是原生的)方式进行转换?感谢

10 个答案:

答案 0 :(得分:105)

试试这个:

function _base64ToArrayBuffer(base64) {
    var binary_string =  window.atob(base64);
    var len = binary_string.length;
    var bytes = new Uint8Array( len );
    for (var i = 0; i < len; i++)        {
        bytes[i] = binary_string.charCodeAt(i);
    }
    return bytes.buffer;
}

答案 1 :(得分:25)

使用TypedArray.from

Uint8Array.from(atob(base64_string), c => c.charCodeAt(0))

将性能与Goran.it答案的for循环版本进行比较。

答案 2 :(得分:23)

由于javascript中的unicode问题,Goran.it的答案不起作用 - https://developer.mozilla.org/en-US/docs/Web/API/WindowBase64/Base64_encoding_and_decoding

我最终使用了Daniel Guerrero的博客http://blog.danguer.com/2011/10/24/base64-binary-decoding-in-javascript/

上给出的功能

功能列在github链接上:https://github.com/danguer/blog-examples/blob/master/js/base64-binary.js

使用这些行

var uintArray = Base64Binary.decode(base64_string);  
var byteArray = Base64Binary.decodeArrayBuffer(base64_string); 

答案 3 :(得分:11)

刚刚找到了base64-arraybuffer,一个小的npm软件包,使用率非常高,上个月(2017-08)下载量为500万。

https://www.npmjs.com/package/base64-arraybuffer

对于寻找最佳标准解决方案的人来说,可能就是这样。

答案 4 :(得分:8)

对于Node.js用户:

const myBuffer = Buffer.from(someBase64String, 'base64');

myBuffer的类型为Buffer,它是Uint8Array的子​​类。不幸的是,Uint8Array不是OP所要求的ArrayBuffer。但是,当操作ArrayBuffer时,我几乎总是用Uint8Array或类似的东西包装它,因此它应该接近所要求的。

答案 5 :(得分:4)

Javascript是一个很好的开发环境,所以看起来很奇怪,因为它没有为这个小问题提供解决方案。本页其他地方提供的解决方案可能很慢。这是我的解决方案。它采用内置功能解码base64图像和声音数据网址。

var req = new XMLHttpRequest;
req.open('GET', "data:application/octet;base64," + base64Data);
req.responseType = 'arraybuffer';
req.onload = function fileLoaded(e)
{
   var byteArray = new Int8Array(e.target.response);
   // var shortArray = new Int16Array(e.target.response);
   // var unsignedShortArray = new Int16Array(e.target.response);
   // etc.
}
req.send();

如果基础65字符串格式错误,发送请求将失败。

可能不需要mime类型(应用程序/八位字节)。

在chrome中测试过。应该可以在其他浏览器中使用。

答案 6 :(得分:2)

异步解决方案,当数据量大时最好:

// base64 to buffer
function base64ToBufferAsync(base64) {
  var dataUrl = "data:application/octet-binary;base64," + base64;

  fetch(dataUrl)
    .then(res => res.arrayBuffer())
    .then(buffer => {
      console.log("base64 to buffer: " + new Uint8Array(buffer));
    })
}

// buffer to base64
function bufferToBase64Async( buffer ) {
    var blob = new Blob([buffer], {type:'application/octet-binary'});    
    console.log("buffer to blob:" + blob)

    var fileReader = new FileReader();
    fileReader.onload = function() {
      var dataUrl = fileReader.result;
      console.log("blob to dataUrl: " + dataUrl);

      var base64 = dataUrl.substr(dataUrl.indexOf(',')+1)      
      console.log("dataUrl to base64: " + base64);
    };
    fileReader.readAsDataURL(blob);
}

答案 7 :(得分:2)

纯JS-无字符串中间步骤(无atob)

我写了下面的函数,该函数直接转换base64(在中间步骤不转换为字符串)。想法

  • 获取4个base64字符块
  • 以base64字母查找每个字符的索引
  • 将索引转换为6位数字(二进制​​字符串)
  • 连接四个6位数字,可得到24位数字(存储为二进制字符串)
  • 将24位字符串拆分为三个8位,并分别进行隐式编号并存储在输出数组中
  • corner case:如果输入base64字符串以一/两个=字符结尾,则从输出数组中删除一个/两个数字

以下解决方案允许处理大型输入base64字符串。将字节转换为不带btoa的base64的类似功能为HERE

function base64ToBytesArr(str) {
  const abc = [..."ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"]; // base64 alphabet
  let result = [];

  for(let i=0; i<str.length/4; i++) {
    let chunk = [...str.slice(4*i,4*i+4)]
    let bin = chunk.map(x=> abc.indexOf(x).toString(2).padStart(6,0)).join(''); 
    let bytes = bin.match(/.{1,8}/g).map(x=> +('0b'+x));
    result.push(...bytes.slice(0,3 - (str[4*i+2]=="=") - (str[4*i+3]=="=")));
  }
  return result;
}


// --------
// TEST
// --------


let test = "Alice's Adventure in Wonderland.";  

console.log('test string:', test.length, test);
let b64_btoa = btoa(test);
console.log('encoded string:', b64_btoa);

let decodedBytes = base64ToBytesArr(b64_btoa); // decode base64 to array of bytes
console.log('decoded bytes:', JSON.stringify(decodedBytes));
let decodedTest = decodedBytes.map(b => String.fromCharCode(b) ).join``;
console.log('Uint8Array', JSON.stringify(new Uint8Array(decodedBytes)));
console.log('decoded string:', decodedTest.length, decodedTest);

答案 8 :(得分:0)

我强烈建议您使用正确实现base64规范的npm软件包。

我认识的最好的人是rfc4648

问题是btoa和atob使用二进制字符串而不是Uint8Array,并且尝试与之进行转换很麻烦。为此,在npm中还有很多坏包。我花了很多时间才找到那个人。

该特定程序包的创建者做了一件简单的事情:他们采用了Base64的规范(顺便说是here),并从头到尾正确地实现了它。 (包括规范中其他有用的其他格式,例如Base64-url,Base32等)。这似乎并不多,但显然对许多其他库而言,要求太多了。

是的,我知道我在做些义教活动,但是如果您也想避免浪费时间,也可以使用rfc4648。

答案 9 :(得分:-1)

const str = "this is base64 string"
const encoded = new TextEncoder().encode(str) // is Uint8Array
const buf = encoded.buffer // is ArrayBuffer

实际上,您可以编码/解码任何字符串,而不仅仅是base64字符串。

请注意,您应该编码base64字符串。此代码不能编码为base64!

MDN:https://developer.mozilla.org/en-US/docs/Web/API/TextEncoder

我可以使用... https://caniuse.com/#feat=textencoder

Polyfill:https://github.com/inexorabletash/text-encoding