将base64字符串转换为ArrayBuffer


98

我需要将base64编码字符串转换为ArrayBuffer。base64字符串是用户输入的字符串,它们将从电子邮件中复制和粘贴,因此在加载页面时它们不存在。我想在javascript中做到这一点,而不可能对服务器进行ajax调用。

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

ArrayBuffer到base64编码的字符串

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

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

这看起来不错,但我不知道如何使用代码。

有没有简单的方法(也许是本地方法)进行转换?谢谢

Answers:


147

试试这个:

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;
}

3
请解释一下这里到底发生了什么。
Govinda Sakhare

4
好吧,这很简单,首先我们解码base64字符串(atob),然后创建新的8位无符号整数数组,其长度与解码后的字符串相同。之后,我们迭代字符串,并使用字符串中每个字符的Unicode值填充数组。
Goran.it,2016年

2
来自MDN:Base64是一组类似的二进制到文本编码方案,它们通过将ASCII格式的二进制数据转换为基数64表示形式来表示二进制数据。所述Uint8Array类型数组表示的8位无符号整数数组,并且我们的数据的ASCII码表示(这也是一个8位表)的工作..
Goran.it

3
这是不正确的。它允许javascript将字节解释为字符串,从而影响实际上是真正二进制的数据。
托马什Zato -恢复莫妮卡

4
问题是,一个)不是每一个字节序列是有效的Unicode B)不是在Unicode的每个字符是一个字节那么bytes[i] = binary_string.charCodeAt(i);可能是错的
混合

52

使用TypedArray.from

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

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


2
对于喜欢这种单线的人来说,请记住Uint8Array.from与某些浏览器仍然缺乏兼容性。
IzumiSy


rails编译器无法处理此字符串,并且失败ExecJS::RuntimeError: SyntaxError: Unexpected token: operator (>);(第5
条路

3
这不是数组缓冲区。这是类型化数组。您可以通过.buffer返回值的属性访问数组缓冲区Uint8Array
oligofren

4
@Saites,atob或没什么问题btoa,您只需给他们有效的输入即可。atob需要有效的base64字符串,否则将引发错误。并且btoa需要一个有效的字节字符串(也称为二进制字符串),该字符串是包含0-255范围内的字符的字符串。如果您的字符串中的字符超出该范围,btoa将引发错误。
GetFree

34

由于javascript中的unicode问题,Goran.it的答案不起作用-https: //developer.mozilla.org/zh-CN/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); 

1
该方法比使用atob快2倍。
xiaoyu2er

4
您能举一个无法解决的例子吗?本文讨论编码任意字符串,其中可能包含unicode字符,但根本不适用atob
Rive

1
decodeArrayBuffer返回一个ArrayBuffer大小总是被3整除的,我不知道它是设计还是错误。我将在github项目中询问。
ceztko

@ceztko可能是(偶然)设计的。base64编码算法采用3个字节的组,并将其转换为4个字符。该解码方法可能会分配一个ArrayBuffer,其长度为base64String.length / 4 * 3个字节,并且在完成后再也不会截断任何未使用的字节。
AlwaysLearning

1
@AlwaysLearning,这意味着它可能已出错,因为剩余的零字节可能会破坏预期的输出内容。
ceztko


9

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

// 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);
}

6

Javascript是一个很好的开发环境,因此似乎比它不能为这个小问题提供解决方案更奇怪。此页面其他地方提供的解决方案可能很慢。这是我的解决方案。它采用了内置功能,可对base64图像和声音数据URL进行解码。

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类型(应用程序/八位位组)可能是不必要的。

经过镀铬测试。应该可以在其他浏览器上使用。


1
这对我来说是简单而干净的完美解决方案。我很快在Firefox,IE 11,Edge中对其进行了测试,并且运行良好!
cs-NET

与最初的问题无关
James Newton

我不确定它在IE11中如何为您工作,但出现Access Denied错误,这似乎是CORS的限制。
Sergiu

6

对于Node.js用户:

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

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


2

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

我编写了以下函数,该函数以直接方式转换base64(在中间步骤不转换为字符串)。理念

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

下面的解决方案允许处理大型输入base64字符串。这里没有将btoa转换为base64的类似功能


这样就不会缺少“。”?
Gillsoft AB

在浏览器中测试,我不确定这是否是预期的结果?“爱丽丝梦游仙境”。(即最后一个角色是NaN)
Gillsoft AB

1
@GillsoftAB感谢您提供此信息-您是对的-我已解决问题
KamilKiełczewski

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.