ChatGPT解决这个技术问题 Extra ChatGPT

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

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

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

这是使用 javascript 进行 base64_encode 和 base64_decode 的最佳方式。请参阅下面的链接。 phpjs.org/functions/base64_encode:358 phpjs.org/functions/base64_decode:357
这是 base64 编码/解码的 another jquery plugin
检查 microjs:microjs.com/#base64

L
Lukas Liesis

您可以使用 btoa()atob() 与 base64 编码相互转换。

关于这些函数接受/返回什么的评论似乎有些混乱,所以……

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

atob() 返回一个“字符串”,其中每个字符代表一个 8 位字节——也就是说,它的值将介于 0 和 0xff 之间。这并不意味着它是 ASCII ——大概如果你使用这个函数,你希望使用二进制数据而不是文本。

也可以看看:

如何使用 Javascript 和 XMLHttpRequest 加载二进制图像数据?

这里的大多数评论都已过时。您可以同时使用 btoa()atob(),除非您支持真正过时的浏览器。

在这里检查:

https://caniuse.com/?search=atob

https://caniuse.com/?search=btoa


请注意,这也适用于 webkit 浏览器,例如 Safari。
请注意 Unicode 字符串的特殊注意事项:developer.mozilla.org/En/DOM/Window.btoa#Unicode_Strings btoa 和 atob 仅适用于基于 ASCII 的字符串。作为美国人,您可能不会注意到有什么不同……但是当您第一次使用重音字符时,您的代码会中断。
如果 str 是 UFT8,您应该使用 btoa(unescape(encodeURIComponent(str))))
请参阅我的编辑,@Triynko。这些不打算用于处理文本、句号。
它的发音是 b to aa to b,b 代表二进制,a 代表 ASCII
P
Peter Mortensen

From here

/**
*
*  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" 会出现许多其他选项,以上是第一个选项。


这在 base64 编码非标准时也很有用;在我的情况下,没有使用“/”字符,而“?”而是使用了字符,这意味着即使在 Chrome atob() 中也不会解码传入的 base64 字符串。
请注意此代码 - 它会尝试将您的字符串解释为 UTF-8 编码的字符串。我们有一个例子,我们有一个二进制字符串(即字符串中的每个字符都应该被解释为一个字节),这个代码确实破坏了数据。阅读来源,卢克。
如果您使用来自 webtoolkito 信息的代码,请不要忘记版权: /** * * Base64 编码/解码 * webtoolkit.info * **/
确保大多数二进制编码/解码安全所需的一切都是为了删除 utf8 编码方法中的有问题的 string = string.replace(/\r\n/g,"\n"); 语句。
@Marius:我想知道他们为什么会首先包含 string = string.replace(/\r\n/g,"\n");,哈哈。这就像“哦,让我们对这个字符串进行编码,但首先,我们为什么不完全没有充分理由地随机标准化所有换行符”。在任何情况下都应该从课堂上删除它。
N
NewUser134

互联网浏览器 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 中将普通文本编码为 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 = new Buffer('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)

Bower 安装 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=');
}]);

此答案基于原始代码,不包括对此处其他答案中发布的代码的更新。
建议的 NodeJS 解决方案已被弃用。
new Buffer() 已弃用,请改用 Buffer.from()
P
Peter Mortensen

Sunny's code 很好,只是它在 Internet Explorer 7 中因引用“this”而中断。通过用“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;
    }
}

哦,我的错,我从浏览器 URL 中获取输入;在哪里 |转换为 %7C;因此编码也错误。
我知道这真的很老了,但我看到这个函数在不止一个地方使用过,关键字符串实际上是 65 个字符,而不是 64 个。字符串不是标准规范,我不确定这是否重要,但只是想知道如果是的话?
“使用严格”;是什么打破了“this”和“with”等其他类型元素,从我读过的内容来看,“eval”受到了抨击。所有关于滥用的错误想法。就我个人而言,我不明白为什么 JavaScript 需要沿着它前进的路线走下去,它从来就不是一个紧密绑定的程序,并且变得比现在更复杂。如果你想被绑定,那就为 javascript 做一个编译器。
我尝试使用此函数,但收到错误: 由:org.mozilla.javascript.EcmaError:TypeError:在对象 teste teste teste 中找不到函数替换我正在尝试使用“teste teste teste”对 .txt 进行编码。任何人都知道为什么会出现这个错误?
@JonathanWagner - 有 64 个字符用于正常编码。第 65 个字符用于填充它们,输入字符串没有可被 3 整除的字符数。
P
Peter Mortensen

您可以使用 btoa(到 Base64)和 atob(从 Base64)。

对于 Internet Explorer 9 及更低版本,请尝试 jquery-base64 插件:

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

为什么一切都需要一个 jQuery 插件:c 这只是核心 JavaScript 功能,与 DOM 或 jQuery 无关
这不是核心功能,否则不会有那么多不同的高票答案(包括自己动手做的 tl;dr 代码)。所以,恕我直言,这实际上是 jQuery 的一个很好的用例(一个班轮,甚至可以在 Android 的 WebView 中工作)——如果它已经是一个依赖项,那就更是如此。
我喜欢将这样的代码片段安装到 jQuery 中,主要是因为它们将存在于受控命名空间中。如果您不使用 AMD 或 CommonJS 或类似的设计模式,那么您的全局命名空间很容易被一堆随机函数弄得一团糟。
@Risadinha - 除了它的功能根本不依赖或扩展任何 jQuery ......实际上,它的代码中对 jQuery 的唯一引用是将它附加到 jQuery 对象......所以将它附加到 jQuery 有什么意义,因此需要jQuery 使用?只需让它成为自己的 1 衬里 base64.encode(...)base64.decode(...) ...当它具有零 jQuery 特定功能时将其附加到 jQuery 绝对没有意义...
没有请求 jQuery。不是一个简单的旧 JS 问题的有效答案。
R
Rocky Kev

从已接受答案下方的评论(由 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 演示

常量输入 = document.getElementsByTagName('input')[0];常量 btnConv = document.getElementById('btnConv');常量 btnDeConv = document.getElementById('btnDeConv'); input.value = "敏捷的棕狐跳过懒狗"; btnConv.addEventListener('click', () => { const txt = input.value; const b64 = btoa(unescape(encodeURIComponent(txt))); input.value = b64; btnDeConv.style.display = 'block'; btnConv.style.display = '无'; }); btnDeConv.addEventListener('click', () => { var b64 = input.value; var txt = decodeURIComponent(escape(window.atob(b64))); input.value = txt; btnConv.style.display = 'block '; btnDeConv.style.display = '无'; }); input{width:500px;} #btnDeConv{display:none;}

.

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

str = "敏捷的棕色狐狸跳过懒惰的狗"; $('输入').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;}


确认一下,这支持 UTF-8 字符吗?
@Crashalot我意识到这已经晚了两年,但是确实如此。当我键入此内容时,我也刚刚意识到您提供了可能使 UTF8 工作的编辑。
对于在这里寻找与 Node.js 一起使用的良好解决方案的任何人,我可以确认这是可行的。对于 Node 中的解码,我使用了:Buffer.from(b64data, 'base64').toString();
有人可以解释一下 unescapeescape 在这个解决方案中做了什么吗?
@Sammi MDN 有 the explanationthis 绝对是正确的方式
P
Peter Mortensen

_utf8_decode 的两种实现中都有几个错误。 c1c2 由于 var 语句的错误使用而被分配为全局变量,并且 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;
}

@Daan 当我在 2011 年写这个答案时,我没有足够的代表来编辑答案。
IE7?我想我们应该停止为此浪费时间编写代码,除非我们开发人员强迫他们这样做,否则人们不会停止使用这种旧技术!
@RonanDejhero 它在 IE7 中不起作用吗?我不记得我是否在那个特定的浏览器中测试过。
我的意思是,如果它在 IE7 中不起作用,没有人应该关心!我没有测试也不会测试它:)
J
John

这个问题及其答案为我指明了正确的方向。尤其是 Unicode,不能使用 atob 和 btoa “香草”,而现在一切都是 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 解码相比,这些函数的执行速度快如闪电,因为 btoa 和 atob 在解释器之外执行。

如果您可以忽略旧 Internet Explorer 和旧手机(如 iPhone 3?),这应该是一个很好的解决方案。


这是来自 MDN 的吗?
这个答案挽救了我的理智。有关其他信息 - 在使用“b64EncodeUnicode()”之后,您可以在 PHP 中对结果字符串安全地使用“base64_decode()”。
R
Rix

对于较新的浏览器将 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')
};

q
qux

如果你使用 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
你说的对。抱歉,我只是通过 Node.js 进行测试。
P
Peter Mortensen

基本上我只是稍微清理了 the original code,所以 JSLint 并没有太多抱怨,而且我在评论中将标记为私有的方法设置为私有。我还添加了我自己项目中需要的两个方法,即 decodeToHexencodeFromHex

编码:

var Base64 = (function() {
    "use strict";

    var _keyStr = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=";

    var _utf8_encode = function (string) {

        var utftext = "", c, n;

        string = string.replace(/\r\n/g,"\n");

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

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

    var _utf8_decode = function (utftext) {
        var string = "", i = 0, 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;
    };

    var _hexEncode = function(input) {
        var output = '', i;

        for(i = 0; i < input.length; i++) {
            output += input.charCodeAt(i).toString(16);
        }

        return output;
    };

    var _hexDecode = function(input) {
        var output = '', i;

        if(input.length % 2 > 0) {
            input = '0' + input;
        }

        for(i = 0; i < input.length; i = i + 2) {
            output += String.fromCharCode(parseInt(input.charAt(i) + input.charAt(i + 1), 16));
        }
        return output;
    };

    var encode = function (input) {
        var output = "", chr1, chr2, chr3, enc1, enc2, enc3, enc4, i = 0;

        input = _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 += _keyStr.charAt(enc1);
            output += _keyStr.charAt(enc2);
            output += _keyStr.charAt(enc3);
            output += _keyStr.charAt(enc4);
        }
        return output;
    };

    var decode = function (input) {
        var output = "", chr1, chr2, chr3, enc1, enc2, enc3, enc4, i = 0;

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

        while (i < input.length) {

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

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

            output += String.fromCharCode(chr1);

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

        }

        return _utf8_decode(output);
    };

    var decodeToHex = function(input) {
        return _hexEncode(decode(input));
    };

    var encodeFromHex = function(input) {
        return encode(_hexDecode(input));
    };

    return {
        'encode': encode,
        'decode': decode,
        'decodeToHex': decodeToHex,
        'encodeFromHex': encodeFromHex
    };
}());

我最初认为将输出串联展开到单独的语句中会更优化,但是在我考虑了几秒钟之后,这应该会更加低效,因为 Javascript 字符串是不可变的,并且在工作时会导致 4 个潜在的巨大数据 blob 副本带有大型二进制数据文件。首先将 4 个字符连接在一起然后构建一个新字符串是一个更安全的选择。我希望我肯定知道一种更好的字符串构建方法,它肯定会在所有平台上都有效。 (甚至IE6)
我在清理最初发布的代码时没有考虑性能。我只是使它更具可读性,并通过使用显示模块模式使原始注释中标记为私有的方法实际上是私有的。我相信它也可以在性能方面进行优化。不太确定垃圾收集何时开始,并且通过 Javascript 散列大文件并不是很常见(或者在任何情况下都可能不是最佳解决方案)。
有趣的是,这段代码是如何生活在这里的。此页面上已经有 3 个不同的版本。
P
Peter Mortensen

请注意,这不适用于原始 Unicode 字符串!请参阅 Unicode 部分 here

编码语法

var encodedData = window.btoa(stringToEncode);

解码语法

var decodedData = window.atob(encodedData);


指向 unicode 部分的直接链接:developer.mozilla.org/en-US/docs/Web/API/…
P
Peter Mortensen

我已经手动将这些编码和解码方法重写为除了十六进制之外的模块化格式,以实现跨平台/浏览器兼容性以及真正的私有范围,如果由于速度而存在,则使用 btoaatob而不是使用自己的编码:

https://gist.github.com/Nijikokun/5192472

用法:

base64.encode(/* String */);
base64.decode(/* String */);

utf8.encode(/* String */);
utf8.decode(/* String */);

m
magikMaker

要使 Base64 编码的字符串 URL 友好,在 JavaScript 中您可以执行以下操作:

// if this is your Base64 encoded string
var str = 'VGhpcyBpcyBhbiBhd2Vzb21lIHNjcmlwdA=='; 

// make URL friendly:
str = str.replace(/\+/g, '-').replace(/\//g, '_').replace(/\=+$/, '');

// reverse to original encoding
str = (str + '===').slice(0, str.length + (str.length % 4));
str = str.replace(/-/g, '+').replace(/_/g, '/');

另请参阅此小提琴:http://jsfiddle.net/magikMaker/7bjaT/


我会谦虚地建议,使用 encodeURIComponent 很可能会导致开发人员花费更少的精力而获得更好的结果。
encodeURIComponent 将改变 base64 编码字符串的长度,在 URL 中使用 base64 时(例如 docs.python.org/library/base64.html#base64.urlsafe_b64encode),将 '-' 和 '_' 替换为 '+' 和 '/' 是标准做法。没必要生气。
P
Peter Mortensen

如果需要对 HTML 图像对象进行编码,可以编写一个简单的函数,例如:

function getBase64Image(img) {
  var canvas = document.createElement("canvas");
  canvas.width = img.width;
  canvas.height = img.height;
  var ctx = canvas.getContext("2d");
  ctx.drawImage(img, 0, 0);
  var dataURL = canvas.toDataURL("image/png");
  // escape data:image prefix
  return dataURL.replace(/^data:image\/(png|jpg);base64,/, "");
  // or just return dataURL
  // return dataURL
}

通过 id 获取图像的 Base64 编码:

function getBase64ImageById(id){
  return getBase64Image(document.getElementById(id));
}

更多是here


是的,var img = new Image(); img.src = "../images/myPic.png";
P
Peter Mortensen

您可以使用 window.btoawindow.atob...

const encoded = window.btoa('Alireza Dezfoolian'); // encode a string
const decoded = window.atob(encoded); // decode the string

可能使用 MDN 的方式可以让你的工作做得最好......也接受 Unicode...... 使用这两个简单的功能:

// UCS-2 string to Base64 encoded ASCII
function utoa(str) {
    return window.btoa(unescape(encodeURIComponent(str)));
}
// Base64 encoded ASCII to UCS-2 string
function atou(str) {
    return decodeURIComponent(escape(window.atob(str)));
}
// Usage:
utoa('✓ à la mode'); // 4pyTIMOgIGxhIG1vZGU=
atou('4pyTIMOgIGxhIG1vZGU='); // "✓ à la mode"

utoa('I \u2661 Unicode!'); // SSDimaEgVW5pY29kZSE=
atou('SSDimaEgVW5pY29kZSE='); // "I ♡ Unicode!"

MDN 是要走的路Reference
P
Peter Mortensen

我的一个项目需要将 UTF-8 字符串编码为 Base64。在转换为 UTF-8 时,这里的大多数答案似乎都无法正确处理 UTF-16 代理对,因此,为了完整起见,我将发布我的解决方案:

function strToUTF8Base64(str) {

    function decodeSurrogatePair(hi, lo) {
        var resultChar = 0x010000;
        resultChar += lo - 0xDC00;
        resultChar += (hi - 0xD800) << 10;
        return resultChar;
    }

    var bytes = [0, 0, 0];
    var byteIndex = 0;
    var result = [];

    function output(s) {
        result.push(s);
    }

    function emitBase64() {

        var digits =
                'ABCDEFGHIJKLMNOPQRSTUVWXYZ' +
                'abcdefghijklmnopqrstuvwxyz' +
                '0123456789+/';

        function toDigit(value) {
            return digits[value];
        }

        // --Byte 0--    --Byte 1--    --Byte 2--
        // 1111  1122    2222  3333    3344  4444

        var d1 = toDigit(bytes[0] >> 2);
        var d2 = toDigit(
            ((bytes[0] & 0x03) << 4) |
            (bytes[1] >> 4));
        var d3 = toDigit(
            ((bytes[1] & 0x0F) << 2) |
            (bytes[2] >> 6));
        var d4 = toDigit(
            bytes[2] & 0x3F);

        if (byteIndex === 1) {
            output(d1 + d2 + '==');
        }
        else if (byteIndex === 2) {
            output(d1 + d2 + d3 + '=');
        }
        else {
            output(d1 + d2 + d3 + d4);
        }
    }

    function emit(chr) {
        bytes[byteIndex++] = chr;
        if (byteIndex == 3) {
            emitBase64();
            bytes[0] = 0;
            bytes[1] = 0;
            bytes[2] = 0;
            byteIndex = 0;
        }
    }

    function emitLast() {
        if (byteIndex > 0) {
            emitBase64();
        }
    }

    // Converts the string to UTF8:

    var i, chr;
    var hi, lo;
    for (i = 0; i < str.length; i++) {
        chr = str.charCodeAt(i);

        // Test and decode surrogate pairs in the string
        if (chr >= 0xD800 && chr <= 0xDBFF) {
            hi = chr;
            lo = str.charCodeAt(i + 1);
            if (lo >= 0xDC00 && lo <= 0xDFFF) {
                chr = decodeSurrogatePair(hi, lo);
                i++;
            }
        }

        // Encode the character as UTF-8.
        if (chr < 0x80) {
            emit(chr);
        }
        else if (chr < 0x0800) {
            emit((chr >> 6) | 0xC0);
            emit(((chr >> 0) & 0x3F) | 0x80);
        }
        else if (chr < 0x10000) {
            emit((chr >> 12) | 0xE0);
            emit(((chr >>  6) & 0x3F) | 0x80);
            emit(((chr >>  0) & 0x3F) | 0x80);
        }
        else if (chr < 0x110000) {
            emit((chr >> 18) | 0xF0);
            emit(((chr >> 12) & 0x3F) | 0x80);
            emit(((chr >>  6) & 0x3F) | 0x80);
            emit(((chr >>  0) & 0x3F) | 0x80);
        }
    }

    emitLast();

    return result.join('');
}

请注意,代码未经过彻底测试。我测试了一些输入,包括 strToUTF8Base64('衠衢蠩蠨') 之类的内容,并与在线编码工具 (https://www.base64encode.org/) 的输出进行了比较。


这是一项伟大的工作!但是,在函数 emitBase64() 中应该是“return digits.substr(value,1)”,而不是“return digits[value]”。因为错误/偶然发现表情符号和多字节字符。但它通常会编码在线解码器无法解码的内容!这段代码毫无问题地带出了基本的西里尔字母。
J
Johan

这是 window.atob + window.btoa 的缩小 polyfill:

(function(){function t(t){this.message=t}var e="undefined"!=typeof exports?exports:this,r="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=";t.prototype=Error(),t.prototype.name="InvalidCharacterError",e.btoa||(e.btoa=function(e){for(var o,n,a=0,i=r,c="";e.charAt(0|a)||(i="=",a%1);c+=i.charAt(63&o>>8-8*(a%1))){if(n=e.charCodeAt(a+=.75),n>255)throw new t("'btoa' failed: The string to be encoded contains characters outside of the Latin1 range.");o=o<<8|n}return c}),e.atob||(e.atob=function(e){if(e=e.replace(/=+$/,""),1==e.length%4)throw new t("'atob' failed: The string to be decoded is not correctly encoded.");for(var o,n,a=0,i=0,c="";n=e.charAt(i++);~n&&(o=a%4?64*o+n:n,a++%4)?c+=String.fromCharCode(255&o>>(6&-2*a)):0)n=r.indexOf(n);return c})})();
(function (root, factory) {
    if (typeof define === 'function' && define.amd) {
        // AMD. Register as an anonymous module.
        define([], function() {factory(root);});
    } else factory(root);
// node.js has always supported base64 conversions, while browsers that support
// web workers support base64 too, but you may never know.
})(typeof exports !== "undefined" ? exports : this, function(root) {
    if (root.atob) {
        // Some browsers' implementation of atob doesn't support whitespaces
        // in the encoded string (notably, IE). This wraps the native atob
        // in a function that strips the whitespaces.
        // The original function can be retrieved in atob.original
        try {
            root.atob(" ");
        } catch(e) {
            root.atob = (function(atob) {
                var func = function(string) {
                    return atob(String(string).replace(/[\t\n\f\r ]+/g, ""));
                };
                func.original = atob;
                return func;
            })(root.atob);
        }
        return;
    }

        // base64 character set, plus padding character (=)
    var b64 = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=",
        // Regular expression to check formal correctness of base64 encoded strings
        b64re = /^(?:[A-Za-z\d+\/]{4})*?(?:[A-Za-z\d+\/]{2}(?:==)?|[A-Za-z\d+\/]{3}=?)?$/;

    root.btoa = function(string) {
        string = String(string);
        var bitmap, a, b, c,
            result = "", i = 0,
            rest = string.length % 3; // To determine the final padding

        for (; i < string.length;) {
            if ((a = string.charCodeAt(i++)) > 255
                    || (b = string.charCodeAt(i++)) > 255
                    || (c = string.charCodeAt(i++)) > 255)
                throw new TypeError("Failed to execute 'btoa' on 'Window': The string to be encoded contains characters outside of the Latin1 range.");

            bitmap = (a << 16) | (b << 8) | c;
            result += b64.charAt(bitmap >> 18 & 63) + b64.charAt(bitmap >> 12 & 63)
                    + b64.charAt(bitmap >> 6 & 63) + b64.charAt(bitmap & 63);
        }

        // If there's need of padding, replace the last 'A's with equal signs
        return rest ? result.slice(0, rest - 3) + "===".substring(rest) : result;
    };

    root.atob = function(string) {
        // atob can work with strings with whitespaces, even inside the encoded part,
        // but only \t, \n, \f, \r and ' ', which can be stripped.
        string = String(string).replace(/[\t\n\f\r ]+/g, "");
        if (!b64re.test(string))
            throw new TypeError("Failed to execute 'atob' on 'Window': The string to be decoded is not correctly encoded.");

        // Adding the padding if missing, for semplicity
        string += "==".slice(2 - (string.length & 3));
        var bitmap, result = "", r1, r2, i = 0;
        for (; i < string.length;) {
            bitmap = b64.indexOf(string.charAt(i++)) << 18 | b64.indexOf(string.charAt(i++)) << 12
                    | (r1 = b64.indexOf(string.charAt(i++))) << 6 | (r2 = b64.indexOf(string.charAt(i++)));

            result += r1 === 64 ? String.fromCharCode(bitmap >> 16 & 255)
                    : r2 === 64 ? String.fromCharCode(bitmap >> 16 & 255, bitmap >> 8 & 255)
                    : String.fromCharCode(bitmap >> 16 & 255, bitmap >> 8 & 255, bitmap & 255);
        }
        return result;
    };
});

https://github.com/MaxArt2501/base64-js/blob/master/base64.js 的完整版


也许也提供一个正常格式的版本?
A
A T

这是@user850789 的AngularJS Factory 版本:

'use strict';

var ProjectNameBase64Factory = angular.module('project_name.factories.base64', []);

ProjectNameBase64Factory.factory('Base64', function () {
    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 = 0, c2 = 0, c3 = 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;
        }
    };
    return Base64;
});

什么是“AngularJS 工厂”?例如,它实际上是专有名词吗?
P
Peter Mortensen

我宁愿使用 CryptoJS 中的 Base64 编码/解码方法,这是最流行的库,用于使用最佳实践和模式在 JavaScript 中实现的标准和安全加密算法。


P
Peter Mortensen

以下是 atob()btoa() JavaScript 内置函数的 LIVE DEMO

<!DOCTYPE html>
<html>
  <head>
    <style>
      textarea{
        width:30%;
        height:100px;
      }
    </style>
    <script>
      // encode string to base64
      function encode()
      {
        var txt = document.getElementById("txt1").value;
        var result = btoa(txt);
        document.getElementById("txt2").value = result;
      }
      // decode base64 back to original string
      function decode()
      {
        var txt = document.getElementById("txt3").value;
        var result = atob(txt);
        document.getElementById("txt4").value = result;
      }
    </script>
  </head>
  <body>
    <div>
      <textarea id="txt1">Some text to decode
      </textarea>
    </div>
    <div>
      <input type="button" id="btnencode" value="Encode" onClick="encode()"/>
    </div>
    <div>
      <textarea id="txt2">
      </textarea>
    </div>
    <br/>
    <div>
      <textarea id="txt3">U29tZSB0ZXh0IHRvIGRlY29kZQ==
      </textarea>
    </div>
    <div>
      <input type="button" id="btndecode" value="Decode" onClick="decode()"/>
    </div>
    <div>
      <textarea id="txt4">
      </textarea>
    </div>
  </body>
</html>

N
Nico

对于我的项目,我仍然需要支持 IE7 并使用大量输入进行编码。

根据 Joe Dyndale 提出的代码和 Marius 在评论中的建议,可以通过使用数组而不是字符串构造结果来提高 IE7 的性能。

这是编码的示例:

var encode = function (input) {
    var output = [], chr1, chr2, chr3, enc1, enc2, enc3, enc4, i = 0;

    input = _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.push(_keyStr.charAt(enc1));
        output.push(_keyStr.charAt(enc2));
        output.push(_keyStr.charAt(enc3));
        output.push(_keyStr.charAt(enc4));

    }

    return output.join("");
};

P
Peter Mortensen

好吧,如果您使用的是 Dojo。它为我们提供了直接编码或解码为 Base64 的方法。

尝试这个:

使用 dojox.encoding.base64 对字节数组进行编码:

var str = dojox.encoding.base64.encode(myByteArray);

要解码 Base64 编码的字符串:

var bytes = dojox.encoding.base64.decode(str);

P
Peter Mortensen

虽然需要做更多工作,但如果您想要一个高性能的原生解决方案,您可以使用一些 HTML5 函数。

如果您可以将数据放入 Blob,那么您可以使用 FileReader.readAsDataURL() 函数来获取 data:// URL 并切掉它的前面以获取 Base64 数据。

但是,您可能需要进行进一步处理才能对数据进行 urldecode,因为我不确定 data:// URL 是否对 + 字符进行了转义,但这应该很简单。


P
Peter Mortensen

使用 js-base64 库作为

btoa() 不适用于表情符号

var str = "我很有趣😂"; console.log("原始字符串:", str); var encodedStr = Base64.encode(str) console.log("编码字符串:", encodedStr); var decodedStr = Base64.decode(encodedStr) console.log("解码字符串:", decodedStr);


P
Peter Mortensen

当我使用

btoa("☸☹☺☻☼☾☿"))

我得到:

错误 InvalidCharacterError:要编码的字符串包含 Latin1 范围之外的字符。

我发现文档 Unicode strings 提供了如下解决方案。

函数 toBinary(string) { const codeUnits = new Uint16Array(string.length); for (let i = 0; i < codeUnits.length; i++) { codeUnits[i] = string.charCodeAt(i); } return String.fromCharCode(...new Uint8Array(codeUnits.buffer)); } function fromBinary(binary) { const bytes = new Uint8Array(binary.length); for (let i = 0; i < bytes.length; i++) { bytes[i] = binary.charCodeAt(i); } return String.fromCharCode(...new Uint16Array(bytes.buffer)); } const myString = "☸☹☺☻☼☾☿" // console.log(btoa(myString)) // 错误 InvalidCharacterError:要编码的字符串包含 Latin1 范围之外的字符。 const 转换 = toBinary(myString) const 编码 = btoa(converted) console.log(encoded) const decoded = atob(encoded) const original = fromBinary(decoded) console.log(original);


我只是复制粘贴来帮助不想点击链接的人...
O
Oded BD

2022 年弃用警告更新

我在我的 vscode 上看到了弃用警告

This function is only provided for compatibility with legacy web platform APIs and should never be used in new code, 
because they use strings to represent binary data and predate the introduction of typed arrays in JavaScript. 
For code running using Node.js APIs, 
converting between base64-encoded strings and binary data should be performed using Buffer.from(str, 'base64') andbuf.toString('base64').

在搜索了更多之后,我发现这个问题说它没有被弃用

https://github.com/microsoft/TypeScript/issues/45566

所以解决web JS上的弃用警告,使用window.btoa,警告就会消失。


l
luiscla27

没有 btoa 中间步骤的 JavaScript(没有库)

在你写的关于字符串转换的问题标题中,但在你谈论二进制数据(图片)的问题中,这是一个从 PNG 图片二进制数据开始进行正确转换的函数(细节和反转转换是 here)。

https://i.stack.imgur.com/g2aN7.png

函数 bytesArrToBase64(arr) { const abc = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; // base64 字母 const bin = n => n.toString(2).padStart(8,0); // 将 num 转换为 8 位二进制字符串 const l = arr.length let result = ''; for(让 i=0; i<=(l-1)/3; i++) { 让 c1 = i*3+1>=l; // 当 "=" 结束时的情况 let c2 = i*3+2>=l; // 当 "=" 结束时的情况 let chunk = bin(arr[3*i]) + bin(c1? 0:arr[3*i+1]) + bin(c2? 0:arr[3*i +2]);让 r = chunk.match(/.{1,6}/g).map((x,j)=> j==3&&c2 ? '=' :(j==2&&c1 ? '=':abc[+( '0b'+x)]));结果 += r.join(''); } 返回结果; } // TEST const pic = [ // PNG 二进制数据 0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a, 0x00, 0x00, 0x00, 0x0d, 0x49, 0x48, 0x44, 0x52, 0x00, 0x00, 0x , 0x10, 0x00, 0x00, 0x00, 0x10, 0x08, 0x06, 0x00, 0x00, 0x00, 0x1f, 0xf3, 0xff, 0x61, 0x00, 0x00, 0x00, 0x01, 0x73, 0xae 0x, 0x, 0x, 0x, 0x, 0x, , 0x1c, 0xe9, 0x00, 0x00, 0x01, 0x59, 0x69, 0x54, 0x58, 0x74, 0x58, 0x4d, 0x4c, 0x3a, 0x63, 0x6f, 0x6d, 0x2e, 0x61, 0x64, 0x6f, 0x62, 0x65, 0x2e, 0x78 , 0x6d, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x78, 0x3a, 0x78, 0x6d, 0x70, 0x6d, 0x65, 0x74, 0x61, 0x20, 0x78, 0x6d, 0x6c, 0x6e, 0x73, 0x3a, 0x78 , 0x3d, 0x22, 0x61, 0x64, 0x6f, 0x62, 0x65, 0x3a, 0x6e, 0x73, 0x3a, 0x6d, 0x65, 0x74, 0x61, 0x2f, 0x22, 0x20, 0x78, 0x3a, 0x78, 0x6d, 0x70, 0x74, 0x6b , 0x3d, 0x22, 0x58, 0x4d, 0x50, 0x20, 0x43, 0x6f, 0x72, 0x65, 0x20, 0x35, 0x2e, 0x34, 0x2e, 0x30, 0x22, 0x3e, 0x0a, 0x20, 0x20, 0x20, 0x3c, 0x72, 0x64 , 0x66, 0x3a, 0x52, 0x44, 0x46, 0x20, 0x78, 0x6d, 0x6c, 0x6e, 0x73, 0x3a, 0x72, 0x64, 0x66, 0x3 d, 0x22, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x77, 0x77, 0x77, 0x2e, 0x77, 0x33, 0x2e, 0x6f, 0x72, 0x67, 0x2f, 0x31, 9, 03x 0x30, 0x32, 0x2f, 0x32, 0x32, 0x2d, 0x72, 0x64, 0x66, 0x2d, 0x73, 0x79, 0x6e, 0x74, 0x61, 0x78, 0x2d, 0x6e, 0x73, 0x23, 0x22, 0x3e, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3c, 0x72, 0x64, 0x66, 0x3a, 0x44, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x72, 0x64, 0x66, 0x3a, 0x61, 0x62, 0x6f, 0x75, 0x74, 0x3d, 0x22, 0x22, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x78, 0x6d, 0x6c, 0x6e, 0x73, 0x3a, 0x74, 0x69, 0x66, 0x66, 0x3d, 0x22, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x6e, 0x73, 0x2e, 0x61, 0x64, 0x6f, 0x62, 0x65, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x74, 0x69, 0x66, 0x66, 0x2f, 0x31, 0x2e, 0x30, 0x2f, 0x22, 0x3e, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3c, 0x74, 0x69, 0x66, 0x66, 0x3a, 0x4f, 0x72, 0x69, 0x65, 0x6e, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x3e, 0 x31, 0x3c, 0x2f, 0x74, 0x69, 0x66, 0x66, 0x3a, 0x4f, 0x72, 0x69, 0x65, 0x6e, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x0a, 020, 0x0a, 020, 020, 0x 0x20, 0x20, 0x3c, 0x2f, 0x72, 0x64, 0x66, 0x3a, 0x44, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x3e, 0x0a, 0x20, 0x20, 0x20, 0x3c, 0x2f, 0x72, 0x64, 0x66, 0x3a, 0x52, 0x44, 0x46, 0x3e, 0x0a, 0x3c, 0x2f, 0x78, 0x3a, 0x78, 0x6d, 0x70, 0x6d, 0x65, 0x74, 0x61, 0x3e, 0x0a, 0x4c, 0xc2, 0x27, 0x59, 0x00, 0x00, 0x00, 0xf9, 0x49, 0x44, 0x41, 0x54, 0x38, 0x11, 0x95, 0x93, 0x3d, 0x0a, 0x02, 0x41, 0x0c, 0x85, 0xb3, 0xb2, 0x85, 0xb7, 0x10, 0x6c, 0x04, 0x1b, 0x0b, 0x4b, 0x6f, 0xe2, 0x76, 0x1e, 0xc1, 0xc2, 0x56, 0x6c, 0x2d, 0xbc, 0x85, 0xde, 0xc4, 0xd2, 0x56, 0xb0, 0x11, 0xbc, 0x85, 0x85, 0xa0, 0xfb, 0x46, 0xbf, 0xd9, 0x30, 0x33, 0x88, 0x06, 0x76, 0x93, 0x79, 0x93, 0xf7, 0x92, 0xf9, 0xab, 0xcc, 0xec, 0xd9, 0x7e, 0xd9, 0x7e, 03x 0x8e, 0xf9, 0x75, 0x8c, 0x92, 0xe0, 0x34, 0xe8, 0x27, 0x88, 0xd9, 0xf4, 0x76, 0xcf, 0xb0, 0xaa, 0x45, 0xb2, 0x0e, 0x4a, 0xe4, 0x94, 0x39, 0x59, 0x0c, 0x03, 0x54, 0x14, 0x58, 0xce, 0xbb, 0xea, 0xdb, 0xd1, 0x3b, 0x71, 0x75, 0xb9, 0xa, 0xb9, 0xa, 0x36, 0x3f, 0xdf, 0x4b, 0x95, 0x35, 0x09, 0x09, 0xef, 0x73, 0xfc, 0xfa, 0x85, 0x67, 0x02, 0x3e, 0x59, 0x55, 0x31, 0x89, 0x31, 0x86, 0x31, 0x86, 0x31, 0x86 0x04, 0xda, 0x23, 0x01, 0x01, 0xc8, 0x8c, 0xe5, 0x77, 0x87, 0xbb, 0x65, 0x02, 0x24, 0xa4, 0xad, 0x82, 0xcb, 0x4b, 0x4c, 0x64, 0x050 0x40, 0x3f, 0xbf, 0xe6, 0x68, 0xb6, 0x9f, 0x75, 0x08, 0x63, 0xc8, 0x9a, 0x09, 0x02, 0x25, 0x32, 0x34, 0x48, 0x7e, 0x6, 0, 0f, 5x, 0xa 0xd2, 0x1a, 0x3d, 0x89, 0x38, 0xf5, 0xf1, 0x14, 0xb4, 0x69, 0x6a, 0x4d, 0x15, 0xf5, 0xc9, 0xf0, 0x5c, 0x1a, 0x61, 0x8a, 0x75, 0xd1, 0xe8, 0x3a, 0x2c, 0x41, 0x5d, 0x70, 0x41, 0x20, 0x29, 0xf9, 0x9b, 0xb1, 0x37, 0xc5, 0x4d, 0xfc, 0x45, 0x84, 0x7d, 0x08, 0x8f, 0x89, 0x76, 0x54, 0xf1, 0x1b, 0x19, 0x92, 0xef, 0x2c, 0xbe, 0x46, 0x8e, 0xa6, 0x49, 0x5e, 0x61, 0x89, 0xe4, 0x05, 0x5e, 0x4e, 0xa4, 0x5c, 0x1 0、0x6e、0x9f、0xfc、0x5b、0x00、0x00、0x00、0x00、0x49、0x45、0x4e、0x44、0xae、0x42、0x60、0x82];让 b64pic = bytesArrToBase64(pic); myPic.src = "数据:图像/png;base64,"+b64pic; msg.innerHTML = "Base64 编码图片数据:
" + b64pic; img {缩放:10;图像渲染:像素化; } #msg { word-break: break-all; }


J
Jeroi

这是编码为 base64url 的辅助函数:

base64url (s) {
        var to64url = btao(s);
         // Replace non-url compatible chars with base64url standard chars and remove leading =
        return to64url.replace(/\+/g, '_').replace(/\//g, '-').replace(/=+$/g, '');
    }

btoa 不是 btao
V
Vladimir Ignatyev

您可以在浏览器中使用 btoa()/atob(),但需要进行一些改进,如此处 https://base64tool.com/uncaught-domexception-btoa-on-window/ 和此处 https://developer.mozilla.org/en-US/docs/Web/API/WindowOrWorkerGlobalScope/btoa 所述,以支持 UTF 字符串!