如何在JavaScript中将字符串编码为Base64?

1218

我有一个可以将PNG图像编码为Base64字符串的PHP脚本。

我想使用JavaScript完成同样的事情。我知道如何打开文件,但是不确定如何进行编码。我不习惯处理二进制数据。


2
以下是使用JavaScript进行base64编码和解码的最佳方法。请参见下面的链接。 http://phpjs.org/functions/base64_encode:358 http://phpjs.org/functions/base64_decode:357 - gautamlakum
这是另一个 jQuery 插件用于 Base64 编码/解码:http://archive.plugins.jquery.com/project/base64 - zahid9i
请检查Microjs: http://microjs.com/#base64 - Vinod Srivastav
参考元问题 *基本相同的答案-唯一的区别:错误的更正*。 - Peter Mortensen
33个回答

1337

你可以使用btoa()atob()来转换成和从base64编码转换。

评论中似乎存在一些关于这些函数接受/返回的内容的混淆,因此...

  • btoa()接受一个“字符串”,其中每个字符代表一个8位字节 - 如果您传递包含无法用8位表示的字符的字符串,则它可能会出错。如果您实际上将字符串视为字节数组,则这不是问题,但如果您想要做其他事情,那么您必须首先进行编码。

  • atob()返回一个“字符串”,其中每个字符代表一个8位字节 - 也就是说,它的值将介于00xff之间。这并不意味着它是ASCII - 假定如果您使用该函数,则期望处理二进制数据而不是文本。

另请参阅:


这里的大部分评论已经过时了。除非你需要支持非常老旧的浏览器,否则你可以使用btoa()atob()两个函数。

在这里查看:


51
请注意,这也适用于Webkit浏览器,如Safari。 - Daniel Von Fange
38
请注意 Unicode 字符串的特殊情况:https://developer.mozilla.org/En/DOM/Window.btoa#Unicode_Strings btoa 和 atob 仅适用于基于 ASCII 的字符串。作为一个美国人,您可能不会注意到区别...但第一次使用重音字符时,您的代码将出现错误。 - Dan Esparza
7
看一下我的编辑,@Triynko。这些并不是用来处理文本的,无论如何。 - Shog9
17
yeahbutstill...它用于将字符串转换为base64编码...任何没有醉酒的程序员都会称其为“toBase64”,支持Unicode,并且接着去喝酒。 - user1228
50
它的发音是 b 到 aa 到 b,其中 b 代表二进制,a 代表 ASCII。 - Captain Hypertext
显示剩余17条评论

323

从这里开始:

/**
*
*  Base64 encode / decode
*  http://www.webtoolkit.info/
*
**/
var Base64 = {

    // private property
    _keyStr : "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=",

    // public method for encoding
    encode : function (input) {
        var output = "";
        var chr1, chr2, chr3, enc1, enc2, enc3, enc4;
        var i = 0;

        input = Base64._utf8_encode(input);

        while (i < input.length) {

            chr1 = input.charCodeAt(i++);
            chr2 = input.charCodeAt(i++);
            chr3 = input.charCodeAt(i++);

            enc1 = chr1 >> 2;
            enc2 = ((chr1 & 3) << 4) | (chr2 >> 4);
            enc3 = ((chr2 & 15) << 2) | (chr3 >> 6);
            enc4 = chr3 & 63;

            if (isNaN(chr2)) {
                enc3 = enc4 = 64;
            } else if (isNaN(chr3)) {
                enc4 = 64;
            }

            output = output +
            this._keyStr.charAt(enc1) + this._keyStr.charAt(enc2) +
            this._keyStr.charAt(enc3) + this._keyStr.charAt(enc4);
        }
        return output;
    },

    // public method for decoding
    decode : function (input) {
        var output = "";
        var chr1, chr2, chr3;
        var enc1, enc2, enc3, enc4;
        var i = 0;

        input = input.replace(/[^A-Za-z0-9\+\/\=]/g, "");

        while (i < input.length) {

            enc1 = this._keyStr.indexOf(input.charAt(i++));
            enc2 = this._keyStr.indexOf(input.charAt(i++));
            enc3 = this._keyStr.indexOf(input.charAt(i++));
            enc4 = this._keyStr.indexOf(input.charAt(i++));

            chr1 = (enc1 << 2) | (enc2 >> 4);
            chr2 = ((enc2 & 15) << 4) | (enc3 >> 2);
            chr3 = ((enc3 & 3) << 6) | enc4;

            output = output + String.fromCharCode(chr1);

            if (enc3 != 64) {
                output = output + String.fromCharCode(chr2);
            }
            if (enc4 != 64) {
                output = output + String.fromCharCode(chr3);
            }
        }

        output = Base64._utf8_decode(output);

        return output;
    },

    // private method for UTF-8 encoding
    _utf8_encode : function (string) {
        string = string.replace(/\r\n/g,"\n");
        var utftext = "";

        for (var n = 0; n < string.length; n++) {

            var c = string.charCodeAt(n);

            if (c < 128) {
                utftext += String.fromCharCode(c);
            }
            else if((c > 127) && (c < 2048)) {
                utftext += String.fromCharCode((c >> 6) | 192);
                utftext += String.fromCharCode((c & 63) | 128);
            }
            else {
                utftext += String.fromCharCode((c >> 12) | 224);
                utftext += String.fromCharCode(((c >> 6) & 63) | 128);
                utftext += String.fromCharCode((c & 63) | 128);
            }
        }
        return utftext;
    },

    // private method for UTF-8 decoding
    _utf8_decode : function (utftext) {
        var string = "";
        var i = 0;
        var c = c1 = c2 = 0;

        while ( i < utftext.length ) {

            c = utftext.charCodeAt(i);

            if (c < 128) {
                string += String.fromCharCode(c);
                i++;
            }
            else if((c > 191) && (c < 224)) {
                c2 = utftext.charCodeAt(i+1);
                string += String.fromCharCode(((c & 31) << 6) | (c2 & 63));
                i += 2;
            }
            else {
                c2 = utftext.charCodeAt(i+1);
                c3 = utftext.charCodeAt(i+2);
                string += String.fromCharCode(((c & 15) << 12) | ((c2 & 63) << 6) | (c3 & 63));
                i += 3;
            }
        }
        return string;
    }
}

此外,搜索"JavaScript base64 encoding"会出现很多其他选项,而上面的是第一个。


3
当base64编码是非标准的时候,这也很有用;在我的情况下,“/”字符没有被使用,而是使用了“?”字符,这意味着即使在Chrome中,atob()也无法解码传入的base64字符串。 - Chris Moschini
31
小心这段代码 - 它试图将您的字符串解释为UTF-8编码的字符串。我们曾经遇到过一个情况,其中我们有一个二进制字符串(即字符串中的每个字符应被解释为一个字节),而该代码破坏了数据。阅读源代码,卢克。 - Daniel Yankowsky
13
为了使大多数二进制编码/解码变得安全,只需在UTF-8编码方法中删除可疑的string = string.replace(/\r\n/g,"\n");语句。 - Marius
10
@Marius:我在想,为什么他们一开始要包括 string = string.replace(/\r\n/g,"\n"); 呢,哈哈。这就像是“哦,让我们对这个字符串进行编码,但首先,为什么不毫无理由地随机规范化所有换行符呢”。在任何情况下,都应该将其从类中删除。 - Triynko
2
我不是JavaScript大师,但这段代码似乎存在一个错误:如果chr2是NaN,则其值仍然在语句“enc2 = ((chr1&3)<< 4)|(chr2 >> 4);”中使用。在我的浏览器中,这个问题可以解决,NaN>>4等于0,但我不知道所有的浏览器是否都这样做(此外,NaN/16等于NaN)。 - Jan
显示剩余10条评论

268

Internet Explorer 10+

// Define the string
var string = 'Hello World!';

// Encode the String
var encodedString = btoa(string);
console.log(encodedString); // Outputs: "SGVsbG8gV29ybGQh"

// Decode the String
var decodedString = atob(encodedString);
console.log(decodedString); // Outputs: "Hello World!"

跨浏览器
// Create Base64 Object
var Base64={_keyStr:"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=",encode:function(e){var t="";var n,r,i,s,o,u,a;var f=0;e=Base64._utf8_encode(e);while(f<e.length){n=e.charCodeAt(f++);r=e.charCodeAt(f++);i=e.charCodeAt(f++);s=n>>2;o=(n&3)<<4|r>>4;u=(r&15)<<2|i>>6;a=i&63;if(isNaN(r)){u=a=64}else if(isNaN(i)){a=64}t=t+this._keyStr.charAt(s)+this._keyStr.charAt(o)+this._keyStr.charAt(u)+this._keyStr.charAt(a)}return t},decode:function(e){var t="";var n,r,i;var s,o,u,a;var f=0;e=e.replace(/[^A-Za-z0-9\+\/\=]/g,"");while(f<e.length){s=this._keyStr.indexOf(e.charAt(f++));o=this._keyStr.indexOf(e.charAt(f++));u=this._keyStr.indexOf(e.charAt(f++));a=this._keyStr.indexOf(e.charAt(f++));n=s<<2|o>>4;r=(o&15)<<4|u>>2;i=(u&3)<<6|a;t=t+String.fromCharCode(n);if(u!=64){t=t+String.fromCharCode(r)}if(a!=64){t=t+String.fromCharCode(i)}}t=Base64._utf8_decode(t);return t},_utf8_encode:function(e){e=e.replace(/\r\n/g,"\n");var t="";for(var n=0;n<e.length;n++){var r=e.charCodeAt(n);if(r<128){t+=String.fromCharCode(r)}else if(r>127&&r<2048){t+=String.fromCharCode(r>>6|192);t+=String.fromCharCode(r&63|128)}else{t+=String.fromCharCode(r>>12|224);t+=String.fromCharCode(r>>6&63|128);t+=String.fromCharCode(r&63|128)}}return t},_utf8_decode:function(e){var t="";var n=0;var r=c1=c2=0;while(n<e.length){r=e.charCodeAt(n);if(r<128){t+=String.fromCharCode(r);n++}else if(r>191&&r<224){c2=e.charCodeAt(n+1);t+=String.fromCharCode((r&31)<<6|c2&63);n+=2}else{c2=e.charCodeAt(n+1);c3=e.charCodeAt(n+2);t+=String.fromCharCode((r&15)<<12|(c2&63)<<6|c3&63);n+=3}}return t}}

// Define the string
var string = 'Hello World!';

// Encode the String
var encodedString = Base64.encode(string);
console.log(encodedString); // Outputs: "SGVsbG8gV29ybGQh"

// Decode the String
var decodedString = Base64.decode(encodedString);
console.log(decodedString); // Outputs: "Hello World!"

jsFiddle


使用Node.js

在Node.js中,您可以使用Buffer.fromString将普通文本编码为base64。

/* 
  Buffer() requires a number, array or string as the first parameter, 
  and an optional encoding type as the second parameter.
  The default is "utf8". Possible encoding types are 
  "ascii", "utf8", "ucs2", "base64", "binary", and "hex"
*/
var b = Buffer.from('JavaScript');
/*
  If we don't use toString(), JavaScript assumes we want to convert the 
  object to utf8.
  We can make it convert to other formats by passing the encoding 
  type to toString().
*/

var s = b.toString('base64');

这是如何解码Base64编码字符串的方法:
var b = Buffer.from('SmF2YVNjcmlwdA==', 'base64')
var s = b.toString();

使用Dojo.js
使用dojox.encoding.base64来编码字节数组:
var str = dojox.encoding.base64.encode(myByteArray);

解码Base64编码的字符串:
var bytes = dojox.encoding.base64.decode(str)

安装 angular-base64

<script src="bower_components/angular-base64/angular-base64.js"></script>

angular
    .module('myApp', ['base64'])
    .controller('myController', [

    '$base64', '$scope',
    function($base64, $scope) {

        $scope.encoded = $base64.encode('a string');
        $scope.decoded = $base64.decode('YSBzdHJpbmc=');
}]);

3
这个答案基于原始代码,不包括在其他答案中发布的该代码的更新。 - Eugene Ryabtsev
提议的 NodeJS 解决方案已经过时。 - Alonso Urbano
13
new Buffer()已被弃用,请使用Buffer.from()代替。 - Ivan Rubinson
我将@davidcondrey的跨浏览器Base64对象转换为与TypeScript兼容的版本。可以在这里找到:Github Gist - adampweb
我将@davidcondrey的跨浏览器Base64对象转换为与TypeScript兼容的版本。可以在这里找到:Github Gist - undefined
在Node.js上,由于某种原因,使用Buffer.from("x").toString("base64")进行编码比使用自己的实现(跨浏览器)更快,但使用自己的实现(跨浏览器)进行解码要快得多。 - Legendary Emoji

100

Sunny的代码非常棒,但是由于引用了"this"而在Internet Explorer 7中出现了错误。通过将这些引用替换为"Base64"来修复它。

var Base64 = {
    // private property
    _keyStr : "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=",

    // public method for encoding
    encode : function (input) {
        var output = "";
        var chr1, chr2, chr3, enc1, enc2, enc3, enc4;
        var i = 0;

        input = Base64._utf8_encode(input);

        while (i < input.length) {

            chr1 = input.charCodeAt(i++);
            chr2 = input.charCodeAt(i++);
            chr3 = input.charCodeAt(i++);

            enc1 = chr1 >> 2;
            enc2 = ((chr1 & 3) << 4) | (chr2 >> 4);
            enc3 = ((chr2 & 15) << 2) | (chr3 >> 6);
            enc4 = chr3 & 63;

            if (isNaN(chr2)) {
                enc3 = enc4 = 64;
            } else if (isNaN(chr3)) {
                enc4 = 64;
            }

            output = output +
            Base64._keyStr.charAt(enc1) + Base64._keyStr.charAt(enc2) +
            Base64._keyStr.charAt(enc3) + Base64._keyStr.charAt(enc4);
        }

        return output;
    },

    // public method for decoding
    decode : function (input) {
        var output = "";
        var chr1, chr2, chr3;
        var enc1, enc2, enc3, enc4;
        var i = 0;

        input = input.replace(/[^A-Za-z0-9\+\/\=]/g, "");

        while (i < input.length) {

            enc1 = Base64._keyStr.indexOf(input.charAt(i++));
            enc2 = Base64._keyStr.indexOf(input.charAt(i++));
            enc3 = Base64._keyStr.indexOf(input.charAt(i++));
            enc4 = Base64._keyStr.indexOf(input.charAt(i++));

            chr1 = (enc1 << 2) | (enc2 >> 4);
            chr2 = ((enc2 & 15) << 4) | (enc3 >> 2);
            chr3 = ((enc3 & 3) << 6) | enc4;

            output = output + String.fromCharCode(chr1);

            if (enc3 != 64) {
                output = output + String.fromCharCode(chr2);
            }
            if (enc4 != 64) {
                output = output + String.fromCharCode(chr3);
            }
        }

        output = Base64._utf8_decode(output);

        return output;
    },

    // private method for UTF-8 encoding
    _utf8_encode : function (string) {
        string = string.replace(/\r\n/g,"\n");
        var utftext = "";

        for (var n = 0; n < string.length; n++) {

            var c = string.charCodeAt(n);

            if (c < 128) {
                utftext += String.fromCharCode(c);
            }
            else if((c > 127) && (c < 2048)) {
                utftext += String.fromCharCode((c >> 6) | 192);
                utftext += String.fromCharCode((c & 63) | 128);
            }
            else {
                utftext += String.fromCharCode((c >> 12) | 224);
                utftext += String.fromCharCode(((c >> 6) & 63) | 128);
                utftext += String.fromCharCode((c & 63) | 128);
            }
        }
        return utftext;
    },

    // private method for UTF-8 decoding
    _utf8_decode : function (utftext) {
        var string = "";
        var i = 0;
        var c = c1 = c2 = 0;

        while ( i < utftext.length ) {

            c = utftext.charCodeAt(i);

            if (c < 128) {
                string += String.fromCharCode(c);
                i++;
            }
            else if((c > 191) && (c < 224)) {
                c2 = utftext.charCodeAt(i+1);
                string += String.fromCharCode(((c & 31) << 6) | (c2 & 63));
                i += 2;
            }
            else {
                c2 = utftext.charCodeAt(i+1);
                c3 = utftext.charCodeAt(i+2);
                string += String.fromCharCode(((c & 15) << 12) | ((c2 & 63) << 6) | (c3 & 63));
                i += 3;
            }
        }
        return string;
    }
}

4
哦,我的错,我从浏览器URL中获取了输入;其中 | 被转换为 %7C;因此编码也是错误的。 - Kanagavelu Sugumar
我知道这个很老了,但我在多个地方看到过这个函数的使用,关键字符串实际上是65个字符,而不是64个。该字符串不是标准规范,我不确定它是否重要,但只是想知道它是否有影响? - Jonathan Wagner
"use strict"是破坏'this'和其他类型元素如'with'的关键所在,从我所读到的来看,'eval'也受到了抨击。这些都是滥用的错误想法。个人认为JavaScript为什么要走下去,它从来没有被设计成一个紧密绑定并且比它已经复杂的程序更加复杂的程序。如果你想要被绑定,那就为JavaScript编写一个编译器吧。 - Mark Giblin
我尝试使用这个函数,但是收到了错误信息:Caused by: org.mozilla.javascript.EcmaError: TypeError: Cannot find function replace in object teste teste teste我正在尝试用“teste teste teste”对.txt进行编码。 有人知道为什么会出现这个错误吗? - PRVS
@JonathanWagner - 普通编码使用了64个字符。第65个字符用作填充,以便输入字符串的字符数不可被3整除。 - Kickstart

94

你可以使用btoa(向Base64转换)和atob(从Base64转换)。

对于Internet Explorer 9及以下版本,请尝试使用jquery-base64插件:

$.base64.encode("this is a test");
$.base64.decode("dGhpcyBpcyBhIHRlc3Q=");

151
为什么所有的东西都需要成为 jQuery 插件呢?这只是核心 JavaScript 功能,与 DOM 或 jQuery 没有任何关系。 - EaterOfCode
40
如果这是核心功能,就不会有那么多不同的高票答案(包括自制的简洁代码)。所以,在我看来,这实际上是使用jQuery的一个很好的例子(一行代码,即使在Android的WebView中也能正常工作) - 如果它已经是一个依赖项,那就更好了。 - Risadinha
1
我喜欢将这样的代码片段安装到jQuery中,主要是因为它们将存在于受控名称空间中。如果您没有使用AMD或CommonJS或类似的设计模式,那么您的全局名称空间很容易变得非常混乱,充满了许多随机函数。 - sffc
11
@Risadinha的意思是,这个功能的实现并不依赖于jQuery,也没有扩展jQuery的任何内容。在代码中唯一涉及到jQuery的地方就是将其附加到jQuery对象上。所以将其附加到jQuery上并要求使用jQuery有什么意义呢?只需将它作为自己的一行代码 base64.encode(...)base64.decode(...) 即可。既然它没有任何与jQuery相关的功能,将其附加到jQuery上完全没有意义。 - Jimbo Jonny
1
jQuery没有被请求。这不是对一个普通的JS问题的有效回答。 - metaColin
显示剩余3条评论

92

根据接受答案下方的SET和Stefan Steiger的评论,以下是一份快速摘要,介绍如何在不使用库的情况下对字符串进行Base64编码/解码。

str = "The quick brown fox jumps over the lazy dog";
b64 = btoa(unescape(encodeURIComponent(str)));
str = decodeURIComponent(escape(window.atob(b64)));

纯JavaScript演示

const input = document.getElementsByTagName('input')[0];
const btnConv = document.getElementById('btnConv');
const btnDeConv = document.getElementById('btnDeConv');

input.value = "The quick brown fox jumps over the lazy dog";

btnConv.addEventListener('click', () => {
  const txt = input.value;
  const b64 = btoa(unescape(encodeURIComponent(txt)));
  input.value = b64;
  btnDeConv.style.display = 'block';
  btnConv.style.display = 'none';
});

btnDeConv.addEventListener('click', () => {
  var b64 = input.value;
  var txt = decodeURIComponent(escape(window.atob(b64)));
  input.value = txt;
  btnConv.style.display = 'block';
  btnDeConv.style.display = 'none';
});
input{width:500px;}
#btnDeConv{display:none;}
<div><input type="text" /></div>
<button id="btnConv">Convert</button>
<button id="btnDeConv">DeConvert</button>

jQuery演示 (使用jQuery库进行显示,但不用于编码/解码)

str = "The quick brown fox jumps over the lazy dog";

$('input').val(str);

$('#btnConv').click(function(){
  var txt = $('input').val();
  var b64 = btoa(unescape(encodeURIComponent(txt)));
  $('input').val(b64);
  $('#btnDeConv').show();
});
$('#btnDeConv').click(function(){
  var b64 = $('input').val();
  var txt = decodeURIComponent(escape(window.atob(b64)));
  $('input').val(txt);
});
#btnDeConv{display:none;}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>

<input type="text" />
<button id="btnConv">Convert</button>
<button id="btnDeConv">DeConvert</button>

还可以参考:

Base64 - MDN Web Docs
使用JavaScript判断字符串是否为Base64


确认一下,这个支持UTF-8字符吗? - Crashalot
1
@Crashalot 我知道这已经晚了两年,但是确实可以。我现在打字时也意识到你提供了一个编辑,可能使UTF8起作用。 - tycrek
对于在这里寻找与Node.js兼容的好解决方案的任何人,我可以确认这个方法可行。在Node中进行解码时,我使用了:Buffer.from(b64data, 'base64').toString(); - tycrek
2
有人能解释一下这个解决方案片段中的 unescapeescape 是做什么用的吗? - Sámal Rasmussen
@Sammi MDN有解释 - 这个绝对是正确的方法 - Philzen
2
对于前端:我注意到btoaunescapeescape都被标记为已弃用。这里有更多信息:https://dev59.com/plEG5IYBdhLWcg3wR442 和 https://dev59.com/AF4c5IYBdhLWcg3wa5-M#27926636。 - Rocky Kev

29

如果你使用Node.js,你可以这样做:

let a = Buffer.from('JavaScript').toString('base64');
console.log(a);

let b = Buffer.from(a, 'base64').toString();
console.log(b);

这仅适用于Node.js,而不是浏览器中的JavaScript。 - Crashalot
你是对的。抱歉,我只是用Node.js测试了一下。 - qux

27

两个 _utf8_decode 实现都存在一些错误。由于对 var 语句的错误使用,导致 c1c2 被分配为全局变量,而 c3 则根本没有被初始化或声明。

它可以工作,但是这些变量将覆盖函数外具有相同名称的任何现有变量。

这里有一个不会出现此问题的版本:

// private method for UTF-8 decoding
_utf8_decode : function (utftext) {
    var string = "";
    var i = 0;
    var c = 0, c1 = 0, c2 = 0;

    while ( i < utftext.length ) {

        c = utftext.charCodeAt(i);

        if (c < 128) {
            string += String.fromCharCode(c);
            i++;
        }
        else if((c > 191) && (c < 224)) {
            c1 = utftext.charCodeAt(i+1);
            string += String.fromCharCode(((c & 31) << 6) | (c1 & 63));
            i += 2;
        }
        else {
            c1 = utftext.charCodeAt(i+1);
            c2 = utftext.charCodeAt(i+2);
            string += String.fromCharCode(((c & 15) << 12) | ((c1 & 63) << 6) | (c2 & 63));
            i += 3;
        }
    }
    return string;
}

10
@Daan,当我在2011年写下这个答案时,我的声望还不够编辑答案。 - robbles
4
IE7?我想我们应该停止浪费时间为它编写代码了,除非我们开发人员强制用户放弃这种旧技术,否则人们不会停止使用它! - Rami Dabain
@RonanDejhero 在IE7中不起作用吗?我不记得是否在那个特定的浏览器中进行了测试。 - robbles
1
我想表达的是,如果它在IE7中无法工作,那么没有人应该关心!我没有测试过,也不会测试它 :) - Rami Dabain

22

这个问题及其答案指引我朝正确方向。特别是在涉及Unicode时,atobbtoa不能“原汁原味”地使用,而这些日子 所有东西 都是Unicode…

直接从Mozilla获取了两个很好的函数来实现此目的。
已测试带有Unicode和HTML标签的情况:

function b64EncodeUnicode(str) {
    return btoa(encodeURIComponent(str).replace(/%([0-9A-F]{2})/g, function(match, p1) {
        return String.fromCharCode('0x' + p1);
    }));
}

b64EncodeUnicode('✓ à la mode'); // "4pyTIMOgIGxhIG1vZGU="
b64EncodeUnicode('\n'); // "Cg=="


function b64DecodeUnicode(str) {
    return decodeURIComponent(Array.prototype.map.call(atob(str), function(c) {
        return '%' + ('00' + c.charCodeAt(0).toString(16)).slice(-2);
    }).join(''));
}

b64DecodeUnicode('4pyTIMOgIGxhIG1vZGU='); // "✓ à la mode"
b64DecodeUnicode('Cg=='); // "\n"

相较于使用自定义JavaScript函数进行原始Base64解码,这些函数的性能将会非常快速,因为btoaatob在解释器之外执行。

如果可以忽略旧版Internet Explorer和老款手机(比如iPhone 3?),那么这应该是一个不错的解决方案。


这是来自 MDN 吗? - 1.21 gigawatts
3
https://developer.mozilla.org/en-US/docs/Web/API/WindowOrWorkerGlobalScope/btoa - John
2
这个回答拯救了我的理智。附加信息:在使用 "b64EncodeUnicode()" 后,您可以安全地在 PHP 上使用 "base64_decode()" 处理结果字符串。 - GTCrais

22

为了让较新的浏览器能够将Uint8Array编码为字符串,并将字符串解码为Uint8Array。

const base64 = {
    decode: s => Uint8Array.from(atob(s), c => c.charCodeAt(0)),
    encode: b => btoa(String.fromCharCode(...new Uint8Array(b)))
};

对于Node.js,您可以使用以下方式将字符串、缓冲区或Uint8Array编码为字符串,并从字符串、缓冲区或Uint8Array解码为缓冲区。

const base64 = {
    decode: s => Buffer.from(s, 'base64'),
    encode: b => Buffer.from(b).toString('base64')
};

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接