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


809

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

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


2
这是使用javascript进行base64_encode和base64_decode的最佳方法。请参阅以下链接。phpjs.org/functions/base64_encode:358 phpjs.org/functions/base64_decode:357
gautamlakum 2011年

这是另一个用于base64编码/解码的jquery插件
zahid9i 2012年


Answers:


865

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

关于这些功能接受/返回的内容,评论中似乎有些混乱,因此……

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

  • atob()返回一个“字符串”,其中每个字符代表一个8位字节-也就是说,其值将在0和之间0xff。但这并不意味着它的ASCII -大概,如果您使用此功能在所有的,你还指望用二进制数据,而不是文字来工作。

也可以看看:


47
请注意,这也适用于Webkit浏览器,例如Safari。
Daniel Von Fange 2010年

5
但不适用于带有iOS 4.1的iPhone3G。设置为iPhone4或iPhone时,它可以在模拟器iPhone模拟器上运行。
格兰特M

28
请注意Unicode字符串的特殊注意事项:developer.mozilla.org/En/DOM/Window.btoa#Unicode_Strings btoa和atob仅适用于基于ASCII的字符串。作为美国人,您可能不会注意到有区别……但是,第一次使用带重音符号的字符时,代码将被破坏。
Dan Esparza

70
btoa(unescape(encodeURIComponent(str))))如果str是UFT8,则应使用
设置

4
看到我的编辑,@ Triynko。这些不用于处理文本,句点。
Shog9年

289

从这里

/**
*
*  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编码”上搜索会变成很多其他选项,以上是第一个。


3
当base64编码为非标准时,这也很有用;在我的情况下,不使用“ /”字符,而使用“?” 使用字符代替,这意味着即使在Chrome中,atob()也不会解码传入的base64字符串。
克里斯·莫斯基尼

21
请谨慎使用此代码-它会尝试将您的字符串解释为UTF-8编码的字符串。我们曾经遇到过一个二进制字符串(即,字符串中的每个字符都应解释为一个字节),并且此代码确实破坏了数据。阅读资料,卢克。
Daniel Yankowsky 2012年

11
确保大多数二进制编码/解码安全的所有必要条件,以消除string = string.replace(/\r\n/g,"\n");utf8编码方法中可疑的语句。
Marius

7
@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)。
1

117

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中将普通文本编码为base64的方法:

//Buffer() requires a number, array or string as the first parameter, and an optional encoding type as the second parameter. 
// Default is utf8, possible encoding types are ascii, utf8, ucs2, base64, binary, and hex
var b = new Buffer('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)

凉亭安装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 2014年

建议的NodeJS解决方案已弃用。
弗拉基米尔·努尔19'Sep

94

Sunny的代码很棒,除了它由于引用“ this”而在IE7中中断。通过将此类引用替换为“ 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个字符。该字符串不是标准规范,我不确定这是否重要,但只是想知道如果可以的话?
乔纳森·瓦格纳

“使用严格”;是打破“ this”和其他类型元素(如“ with”)的原因,据我所读,“ eval”受到了抨击。所有关于滥用的想法都错了。就我个人而言,我不明白为什么JavaScript需要顺其自然,这绝不是要紧密地绑定程序并使它变得比现在更复杂。如果要绑定,请为javascript编译器。
Mark Giblin

我尝试使用此函数,但收到错误:引起原因:org.mozilla.javascript.EcmaError:TypeError:在对象teste teste teste中找不到函数替换。我正在尝试使用“ teste teste teste”对.txt进行编码。谁知道为什么这个错误?
PRVS

@JonathanWagner-普通编码使用64个字符。第65个字符用作填充字符,输入字符串中不包含可被3整除的字符。–
Kickstart

90

您可以使用btoa(以base-64为基础)和(以base-64 atob为基础)。

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

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

133
为什么所有的东西都需要一个jQuery插件:c这只是核心的JavaScript功能,它与DOM或jQuery无关
EaterOfCode 2013年

38
这不是核心功能,或者不会有很多不同的高票答案(包括“自己动手tl; dr代码”)。因此,恕我直言,这实际上是jQuery的一个很好的用例(一个衬里,即使在Android的WebView中也可以使用)-如果已经是依赖项,则更多。
Risadinha

1
我喜欢将这样的代码片段安装到jQuery中,主要是因为它们将存在于受控的命名空间中。如果您不使用AMD或CommonJS或类似的设计模式,则全局名称空间很容易因大量随机函数而变得混乱。
sffc

9
@Risadinha-除了它的功能根本不依赖或扩展任何jQuery ...从字面上看,在其代码中对jQuery的唯一引用是将其附加到jQuery对象上。因此,将其附加到jQuery的意义何在,因此需要使用jQuery吗?只需使其成为自己的1个衬板,base64.encode(...)然后base64.decode(...)将其附加到jQuery,当它具有零jQuery特定功能时就完全没有意义了……
Jimbo Jonny

1
不需要jQuery。这不是一个简单的旧JS问题的有效答案。
metaColin

34

从接受的答案下面的评论(由SET和Stefan Steiger撰写),这里快速总结了如何在不需要库的情况下将字符串编码到base64或从base64解码。

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

演示版

(使用jQuery库,但不用于编码/解码)


确认一下,这支持UTF-8字符吗?
Crashalot

1
@Crashalot我意识到这已经太迟了两年,但是是的。我也只是在输入时意识到您提供的编辑可能使UTF8正常工作。
tycrek

对于任何在这里寻找可以与Node.js一起使用的好的解决方案的人,我都可以确认这一工作。对于Node中的解码,我使用了:Buffer.from(b64data, 'base64').toString();
tycrek

26

的两种实现都有两个错误_utf8_decodec1并且c2被指定为全局变量,由于碎使用的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;
}

9
@ Daan,2011
。–麻烦2013年

2
IE7?我想我们应该停止浪费时间为此编写代码,除非我们的开发人员强迫他们这样做,否则人们不会停止使用这种旧技术!
拉米达巴因2014年

@RonanDejhero在IE7中不起作用吗?我不记得我是否在该特定浏览器中进行过测试。
2014年

1
我的意思是,如果它在IE7中不起作用,没有人应该在意!我没有测试,也不会测试它:)
Rami Dabain 2014年

16

我+1了Sunny的答案,但我想回馈我为自己的项目所做的一些更改,以防有人发现它有用。基本上,我只是对原始代码进行了一点清理,因此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)
Marius

我在清理原始发布的代码时没有考虑性能。我只是使它更具可读性,并且使用显示模块模式使原始注释中标记为私有的方法实际上是私有的。我相信它也可以在性能方面进行优化。不确定何时开始垃圾回收,并且通过Javascript对大型文件进行哈希处理并不常见(或者在任何情况下实际上都不是最佳解决方案)。
Joe Dyndale

有趣的是,这段代码在这里生活得如何。此页面上已经有3个不同的版本。
gregn3 2014年

14

对于较新的浏览器,将Uint8Array编码为字符串,然后将字符串解码为Uint8Array。

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

对于Node.js,您可以使用以下代码将字符串,Buffer或Uint8Array编码为字符串,以及从字符串,Buffer或Uint8Array解码为Buffer。

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

13

为了使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/


9
我要谦虚地建议,使用开发人员encodeURIComponent可能会产生更好的结果,而开发人员的工作量却更少。
Pablo Fernandez

11
encodeURIComponent将更改base64编码的字符串的长度,并且在URL中使用base64时(例如docs.python.org/library/base64.html#base64),将“-”和“ _”替换为“ +”和“ /”是标准做法.urlsafe_b64encode)。无需生气。
natevw 2011年


12

我手工重写了这些编码和解码方法,除了将十六进制转换为模块化格式以实现跨平台/浏览器兼容性以及真正的私有作用域之外,还使用了它们,并且使用它们btoaatob如果存在的话)是由于速度而不是利用自己的编码:

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

用法:

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

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

12

这个问题及其答案为我指明了正确的方向。
特别是与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在解释器外部执行。

如果您可以忽略旧的IE和旧的手机(例如iphone 3?),那么这应该是一个很好的解决方案。


10

如果您需要对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));  
} 

这里更多


是的,并且var img = new Image(); img.src =“ ../images/myPic.png”;
pdschuller

7

为我当前正在使用的window.atob+ 的最小化polyfill进行贡献window.btoa

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

6

我宁愿使用来自bas64编码/解码方法CryptoJS,利用最佳实践和模式JavaScript实现标准和安全的加密算法最流行的库。


6

这是@ user850789的AngularJS工厂版本:

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

6

对于我的项目,我需要将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/)的输出进行了比较。


5

对于我的项目,我仍然需要支持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("");
};

5

尽管还有更多工作要做,但是如果您需要高性能的本机解决方案,则可以使用一些HTML5函数。

如果您可以将数据放入Blob,则可以使用FileReader.readAsDataURL()函数获取一个data://URL,然后将其切掉以获取base64数据。

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


5

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

尝试这个:-

要使用dojox.encoding.base64编码字节数组:

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

要解码base64编码的字符串:

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

3

您可以使用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!"

3

这里有一个现场演示atob()btoa()内置函数JS:

<!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>

2

使用js-base64库作为

btoa()不适用于表情符号

var str = "I was funny 😂";
console.log("Original string:", str);

var encodedStr = Base64.encode(str)
console.log("Encoded string:", encodedStr);

var decodedStr = Base64.decode(encodedStr)
console.log("Decoded string:", decodedStr);
<script src="https://cdn.jsdelivr.net/npm/js-base64@2.5.2/base64.min.js"></script>

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.