【问题标题】:Base64 encoding and decoding in client-side Javascript [duplicate]客户端Javascript中的Base64编码和解码[重复]
【发布时间】:2011-02-18 16:47:58
【问题描述】:

JavaScript 中是否有任何方法可用于使用 base64 编码对字符串进行编码和解码?

【问题讨论】:

标签: javascript base64


【解决方案1】:

一些浏览器,如 Firefox、Chrome、Safari、Opera 和 IE10+ 可以原生处理 Base64。看看这个Stackoverflow question。它正在使用btoa() and atob() functions

对于服务器端 JavaScript (Node),可以使用Buffers 进行解码。

如果您要使用跨浏览器解决方案,可以使用 CryptoJS 等现有库或类似以下代码:

http://ntt.cc/2008/01/19/base64-encoder-decoder-with-javascript.html存档

对于后者,您需要彻底测试该功能的跨浏览器兼容性。还有错误has already been reported

【讨论】:

  • 我使用此方法使用 Date URI 方案在 base64 中对 SVG 进行编码。惊喜:这个函数对每个字符进行 urlencode,所以我在目标处得到了这个格式错误的 XML:%3C%3Fxml%20version%3D%271.0%27%20%3F%3E%3Csvg%20xmlns%3D%27http%...
  • Node.js 可以原生做 Base64:new Buffer('Hello, world!').toString('base64');new Buffer('SGVsbG8sIHdvcmxkIQ==', 'base64').toString('ascii');(source)
  • 如果我想做到 URL 安全?
  • 在节点 5+ 中,使用 Buffer.from,因为 new Buffer(string) 已弃用。 Buffer.from(jwt.split('.')[1], 'base64').toString()
【解决方案2】:

php.js 项目包含许多 PHP 函数的 JavaScript 实现。包括base64_encodebase64_decode

【讨论】:

  • php.js 是万恶的化身,属于自己的地狱层。像瘟疫一样避免它。 (更多信息:softwareengineering.stackexchange.com/questions/126671/…
  • 我没有看到太多支持该链接中的全面断言,@Coreus。明智地使用,或者作为一个起点,它是一种完全可以接受的方法,可以在 JS 中为您可能已经知道如何在 PHP 中完成的事情找出等效逻辑。
【解决方案3】:

短而快的 Base64 JavaScript 解码函数,无故障保护:

function decode_base64 (s)
{
    var e = {}, i, k, v = [], r = '', w = String.fromCharCode;
    var n = [[65, 91], [97, 123], [48, 58], [43, 44], [47, 48]];

    for (z in n)
    {
        for (i = n[z][0]; i < n[z][1]; i++)
        {
            v.push(w(i));
        }
    }
    for (i = 0; i < 64; i++)
    {
        e[v[i]] = i;
    }

    for (i = 0; i < s.length; i+=72)
    {
        var b = 0, c, x, l = 0, o = s.substring(i, i+72);
        for (x = 0; x < o.length; x++)
        {
            c = e[o.charAt(x)];
            b = (b << 6) + c;
            l += 6;
            while (l >= 8)
            {
                r += w((b >>> (l -= 8)) % 256);
            }
         }
    }
    return r;
}

【讨论】:

  • Opera 11.62 似乎有 '%256' 部分的问题。用 '&0xff' 替换它就可以了。
  • Tyk 虚拟端点 javascript 代码似乎与 '\x00' 部分有问题。将其替换为 r = r.replace(/\x00/g, '') 使其工作
【解决方案4】:

在基于 Gecko/WebKit 的浏览器(Firefox、Chrome 和 Safari)和 Opera 中,您可以使用 btoa()atob()

原答案:How can you encode a string to Base64 in JavaScript?

【讨论】:

  • 这是一个救生员。我使用了几种不同的实现来解码非常大的 base64 编码字符串,结果总是错误的。 atob() 效果很好!
  • 小问题:Opera 不是基于 Gecko 或 Webkit,它使用自己的渲染引擎 Presto。
  • 哇,谢谢。不知道这些浏览器中有原生 base64 编码器!
  • @PeterOlson 不再是 :)
  • 我知道这是一篇旧帖子,但关于@b2238488 的关注,您可以拆分base64 字符串,使每个令牌的长度为4 的倍数,然后分别解码。结果将与一次解码整个字符串相同。
【解决方案5】:

我在 phpjs.org 上尝试过 Javascript 例程,它们运行良好。

我首先尝试了 Ranhiru Cooray 选择的答案中建议的例程 - http://ntt.cc/2008/01/19/base64-encoder-decoder-with-javascript.html

我发现它们并非在所有情况下都有效。我写了一个这些例程失败的测试用例,并将它们发布到 GitHub 上:

https://github.com/scottcarter/base64_javascript_test_data.git

我还在 ntt.cc 的博客文章中发表了评论以提醒作者(等待审核 - 文章已过时,因此不确定是否会发布评论)。

【讨论】:

    【解决方案6】:

    这是 Sniper 帖子的精简版。它假定格式良好的 base64 字符串没有回车。此版本消除了几个循环,添加了来自 Yaroslav 的 &amp;0xff 修复程序,消除了尾随空值,以及一些代码高尔夫球。

    decodeBase64 = function(s) {
        var e={},i,b=0,c,x,l=0,a,r='',w=String.fromCharCode,L=s.length;
        var A="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
        for(i=0;i<64;i++){e[A.charAt(i)]=i;}
        for(x=0;x<L;x++){
            c=e[s.charAt(x)];b=(b<<6)+c;l+=6;
            while(l>=8){((a=(b>>>(l-=8))&0xff)||(x<(L-2)))&&(r+=w(a));}
        }
        return r;
    };
    

    【讨论】:

    • 甚至更少的字节;D decodeBase64=function(f){var g={},b=65,d=0,a,c=0,h,e="",k=String.fromCharCode,l=f.length;for(a="";91&gt;b;)a+=k(b++);a+=a.toLowerCase()+"0123456789+/";for(b=0;64&gt;b;b++)g[a.charAt(b)]=b;for(a=0;a&lt;l;a++)for(b=g[f.charAt(a)],d=(d&lt;&lt;6)+b,c+=6;8&lt;=c;)((h=d&gt;&gt;&gt;(c-=8)&amp;255)||a&lt;l-2)&amp;&amp;(e+=k(h));return e};
    • 是的,但仅适用于 ASCII。例如,Cyr 字符会被破坏。
    • @MartinKovachev 你能用 Cyr 字符和相应的 base64 编码的示例文本发表新评论吗?也许我们可以修复代码以适应。
    • 这里:类似的东西:тестова фраза
    • @OliverSalzburg 甚至更少生成代码表:) : var g={},k=String.fromCharCode,i;for(i=0;i&lt;64;)g[k(i&gt;61?(i&amp;1)*4|43:i+[65,71,-4][i/26&amp;3])]=i++;
    【解决方案7】:

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

    【讨论】:

      【解决方案8】:

      有人说代码高尔夫吗? =)

      以下是我在与时俱进的同时改善差点的尝试。为您提供方便。

      function decode_base64(s) {
        var b=l=0, r='',
        m='ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/';
        s.split('').forEach(function (v) {
          b=(b<<6)+m.indexOf(v); l+=6;
          if (l>=8) r+=String.fromCharCode((b>>>(l-=8))&0xff);
        });
        return r;
      }
      

      我实际上追求的是异步实现,令我惊讶的是,forEach 与 JQuery 的 $([]).each 方法实现非常同步。

      如果你也有这样疯狂的想法,那么 0 延迟 window.setTimeout 将异步运行 base64 解码,并在完成后执行带有结果的回调函数。

      function decode_base64_async(s, cb) {
        setTimeout(function () { cb(decode_base64(s)); }, 0);
      }
      

      @Toothbrush 建议“像数组一样索引字符串”,并去掉split。这个套路看起来很奇怪,不确定它的兼容性如何,但它确实击中了另一只小鸟,所以让我们来吧。

      function decode_base64(s) {
        var b=l=0, r='',
        m='ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/';
        [].forEach.call(s, function (v) {
          b=(b<<6)+m.indexOf(v); l+=6;
          if (l>=8) r+=String.fromCharCode((b>>>(l-=8))&0xff);
        });
        return r;
      }
      

      在尝试查找有关 JavaScript 字符串作为数组的更多信息时,我偶然发现了这个专业提示,它使用 /./g 正则表达式来遍历字符串。通过替换字符串并消除保留返回变量的需要,这进一步减少了代码大小。

      function decode_base64(s) {
        var b=l=0,
        m='ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/';
        return s.replace(/./g, function (v) {
          b=(b<<6)+m.indexOf(v); l+=6;
          return l<8?'':String.fromCharCode((b>>>(l-=8))&0xff);
        });
      }
      

      但是,如果您正在寻找更传统的东西,也许以下内容更符合您的口味。

      function decode_base64(s) {
        var b=l=0, r='', s=s.split(''), i,
        m='ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/';
        for (i in s) {
          b=(b<<6)+m.indexOf(s[i]); l+=6;
          if (l>=8) r+=String.fromCharCode((b>>>(l-=8))&0xff);
        }
        return r;
      }
      

      我没有尾随的 null 问题,因此已将其删除以保持低于标准,但如果您愿意,应该很容易通过 trim()trimRight() 解决,如果这给您带来问题。

      即。

      return r.trimRight();
      

      注意:

      结果是一个ascii字节串,如果你需要unicode最简单的就是escape这个字节串,然后可以用decodeURIComponent解码得到unicode串。

      function decode_base64_usc(s) {      
        return decodeURIComponent(escape(decode_base64(s)));
      }
      

      由于 escape 已被弃用,我们可以更改我们的函数以直接支持 unicode,而无需 escapeString.fromCharCode,我们可以生成一个 % 转义字符串,以供 URI 解码。

      function decode_base64(s) {
        var b=l=0,
        m='ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/';
        return decodeURIComponent(s.replace(/./g, function (v) {
          b=(b<<6)+m.indexOf(v); l+=6;
          return l<8?'':'%'+(0x100+((b>>>(l-=8))&0xff)).toString(16).slice(-2);
        }));
      }
      

      为@Charles Byrne 编辑:

      不记得为什么我们没有忽略“=”填充字符,可能是在当时不需要它们的规范中使用的。如果我们要修改decodeURIComponent 例程以忽略这些,因为它们不代表任何数据,所以我们应该忽略这些,结果会正确解码示例。

      function decode_base64(s) {
        var b=l=0,
        m='ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/';
        return decodeURIComponent(s.replace(/=*$/,'').replace(/./g, function (v) {
          b=(b<<6)+m.indexOf(v); l+=6;
          return l<8?'':'%'+(0x100+((b>>>(l-=8))&0xff)).toString(16).slice(-2);
        }));
      }
      

      现在调用decode_base64('4pyTIMOgIGxhIG1vZGU=') 将返回编码字符串'✓ à la mode',没有任何错误。

      由于 '=' 被保留为填充字符,如果可以的话,我可以减少我的代码高尔夫差点:

      function decode_base64(s) {
        var b=l=0,
        m='ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/';
        return decodeURIComponent(s.replace(/./g, function (v) {
          b=(b<<6)+m.indexOf(v); l+=6;
          return l<8||'='==v?'':'%'+(0x100+((b>>>(l-=8))&0xff)).toString(16).slice(-2);
        }));
      }
      

      开心!

      【讨论】:

      • 您不需要 split 字符串,因为您可以像数组一样索引 JavaScript 字符串。 s.split('').forEach(function ... 可以替换为 [].forEach.call(s, function ...。它应该更快,因为它不必拆分字符串。
      • “更传统的”对我来说完全被打破了——产生了乱码,到处都是原始文本的痕迹。在 Chrome 上。
      • @Steve Bennett 我在 chrome 中测试了所有变体......它有效。你能提供一个失败的base64字符串示例吗?
      • 三年后?哈。我什至不记得我需要这个做什么。
      • @CharlesByrne 哇,有一段时间了,重温过去很有趣,完全忘记了这一点,我最近一直在使用atobbtoa。您也可以自己删除填充字符,但上述编辑将解决。随着规范的发展,似乎完全弃用 escape 的可能性越来越小。
      【解决方案9】:

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

      跨浏览器

      Re-written and modularized UTF-8 and Base64 Javascript Encoding and Decoding Libraries / Modules for AMD, CommonJS, Nodejs and Browsers. Cross-browser compatible.


      使用 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=');
      }]);
      

      但是如何?

      如果您想了解更多关于 base64 的一般编码方式,尤其是 JavaScript 编码方式,我推荐这篇文章:Computer science in JavaScript: Base64 encoding

      【讨论】:

      • 仅供参考:跨浏览器版本与 c2 和可能的 c1c3 存在一些令人讨厌的泄漏,因此它不适用于上面定义的 "use strict"
      • 使用 Node js 我简化为:new Buffer('SmF2YVNjcmlwdA==', 'base64').toString()。有什么特别的理由不这样做吗?
      • 我知道这是一个旧答案,但 new Buffer() 似乎已被弃用。对于像我这样的新观众,Buffer.from() 应该可以达到与@ecoologic 的回复below 相同的结果@
      【解决方案10】:

      function b64_to_utf8( str ) {
        return decodeURIComponent(escape(window.atob( str )));
      }

      https://developer.mozilla.org/en-US/docs/Web/API/WindowBase64/Base64_encoding_and_decoding#The_.22Unicode_Problem.22

      【讨论】:

      【解决方案11】:

      在 Node.js 中,我们可以用简单的方式做到这一点

      var base64 = 'SGVsbG8gV29ybGQ='
      var base64_decode = new Buffer(base64, 'base64').toString('ascii');
      
      console.log(base64_decode); // "Hello World"
      

      【讨论】:

        【解决方案12】:

        对于没有 atob 方法的 JavaScript 框架,如果您不想导入外部库,这是一个简短的函数。

        它将获得一个包含 Base64 编码值的字符串,并将返回一个解码的字节数组(其中字节数组表示为数字数组,其中每个数字都是 0 到 255 之间的整数)。

        function fromBase64String(str) {
            var alpha = 
            "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
            var value = [];
            var index = 0;
            var destIndex  = 0;
            var padding = false;
            while (true) {
        
                var first  = getNextChr(str, index, padding, alpha);
                var second = getNextChr(str, first .nextIndex, first .padding, alpha);
                var third  = getNextChr(str, second.nextIndex, second.padding, alpha);
                var fourth = getNextChr(str, third .nextIndex, third .padding, alpha);
        
                index = fourth.nextIndex;
                padding = fourth.padding;
        
                // ffffffss sssstttt ttffffff
                var base64_first  = first.code  == null ? 0 : first.code;
                var base64_second = second.code == null ? 0 : second.code;
                var base64_third  = third.code  == null ? 0 : third.code;
                var base64_fourth = fourth.code == null ? 0 : fourth.code;
        
                var a = (( base64_first << 2) & 0xFC ) | ((base64_second>>4) & 0x03);
                var b = (( base64_second<< 4) & 0xF0 ) | ((base64_third >>2) & 0x0F);
                var c = (( base64_third << 6) & 0xC0 ) | ((base64_fourth>>0) & 0x3F);
        
                value [destIndex++] = a;
                if (!third.padding) {
                    value [destIndex++] = b;
                } else {
                    break;
                }
                if (!fourth.padding) {
                    value [destIndex++] = c;
                } else {
                    break;
                }
                if (index >= str.length) {
                    break;
                }
            }
            return value;
        }
        
        function getNextChr(str, index, equalSignReceived, alpha) {
            var chr = null;
            var code = 0;
            var padding = equalSignReceived;
            while (index < str.length) {
                chr = str.charAt(index);
                if (chr == " " || chr == "\r" || chr == "\n" || chr == "\t") {
                    index++;
                    continue;
                }
                if (chr == "=") {
                    padding = true;
                } else {
                    if (equalSignReceived) {
                        throw new Error("Invalid Base64 Endcoding character \"" 
                            + chr + "\" with code " + str.charCodeAt(index) 
                            + " on position " + index 
                            + " received afer an equal sign (=) padding "
                            + "character has already been received. "
                            + "The equal sign padding character is the only "
                            + "possible padding character at the end.");
                    }
                    code = alpha.indexOf(chr);
                    if (code == -1) {
                        throw new Error("Invalid Base64 Encoding character \"" 
                            + chr + "\" with code " + str.charCodeAt(index) 
                            + " on position " + index + ".");
                    }
                }
                break;
            }
            return { character: chr, code: code, padding: padding, nextIndex: ++index};
        }
        

        使用的资源:@​​987654322@

        【讨论】:

          【解决方案13】:

          对于它的价值,我受到其他答案的启发并编写了一个小实用程序,它调用平台特定的 API 以从 Node.js 或浏览器普遍使用:

          /**
           * Encode a string of text as base64
           *
           * @param data The string of text.
           * @returns The base64 encoded string.
           */
          function encodeBase64(data: string) {
              if (typeof btoa === "function") {
                  return btoa(data);
              } else if (typeof Buffer === "function") {
                  return Buffer.from(data, "utf-8").toString("base64");
              } else {
                  throw new Error("Failed to determine the platform specific encoder");
              }
          }
          
          /**
           * Decode a string of base64 as text
           *
           * @param data The string of base64 encoded text
           * @returns The decoded text.
           */
          function decodeBase64(data: string) {
              if (typeof atob === "function") {
                  return atob(data);
              } else if (typeof Buffer === "function") {
                  return Buffer.from(data, "base64").toString("utf-8");
              } else {
                  throw new Error("Failed to determine the platform specific decoder");
              }
          }

          【讨论】:

            【解决方案14】:

            现代浏览器内置了用于Base64编码btoa()和解码atob()的javascript函数。有关旧版浏览器支持的更多信息:https://caniuse.com/?search=atob

            但是,请注意 atobbtoa 函数仅适用于 ASCII 字符集。 如果你需要 UTF-8 字符集的 Base64 函数,你可以这样做:

            function base64_encode(s) {      
                return btoa(unescape(encodeURIComponent(s)));
            }
            function base64_decode(s) {      
                return decodeURIComponent(escape(atob(s)));
            }
            

            【讨论】:

            • 谢谢!这是非常好的和简单的
            【解决方案15】:

            Base64 Win-1251 解码,用于acsi 或 iso-8859-1 以外的编码。

            事实证明,我在这里看到的所有脚本都将 Cyrillic Base64 转换为 iso-8859-1 编码。奇怪的是没有人注意到这一点。

            因此,要恢复西里尔字母,只需将文本从 iso-8859-1 额外转码到 windows-1251 就足够了。

            我认为其他语言也是如此。只需将 Cyrilic windows-1251 更改为您的即可。

            ...感谢 Der Hochstapler 提供的代码,我从他的评论中获取...过度评论,这有点不寻常。

            JScript 代码(仅适用于 Windows 桌面)(ActiveXObject) - 1251 文件编码

            decode_base64=function(f){var g={},b=65,d=0,a,c=0,h,e="",k=String.fromCharCode,l=f.length;for(a="";91>b;)a+=k(b++);a+=a.toLowerCase()+"0123456789+/";for(b=0;64>b;b++)g[a.charAt(b)]=b;for(a=0;a<l;a++)for(b=g[f.charAt(a)],d=(d<<6)+b,c+=6;8<=c;)((h=d>>>(c-=8)&255)||a<l-2)&&(e+=k(h));return e};
            sDOS2Win = function(sText, bInsideOut) {
                var aCharsets = ["iso-8859-1", "windows-1251"];
                sText += "";
                bInsideOut = bInsideOut ? 1 : 0;
                with (new ActiveXObject("ADODB.Stream")) { //http://www.w3schools.com/ado/ado_ref_stream.asp
                    type = 2; //Binary 1, Text 2 (default) 
                    mode = 3; //Permissions have not been set 0,  Read-only 1,  Write-only 2,  Read-write 3,  
                    //Prevent other read 4,  Prevent other write 8,  Prevent other open 12,  Allow others all 16
                    charset = aCharsets[bInsideOut]; 
                    open();
                    writeText(sText);
                    position = 0;
                    charset = aCharsets[1 - bInsideOut];
                    return readText();
                }
            }
            var base64='0PPx8ero5SDh8+ru4uroIQ=='
            text = sDOS2Win(decode_base64(base64), false );
            WScript.Echo(text)
            var x=WScript.StdIn.ReadLine();
            

            【讨论】:

              【解决方案16】:

              前端:上面的解决方案很好,但后端很快......

              NodeJS - 没有弃用

              使用Buffer.from

              > inBase64 = Buffer.from('plain').toString('base64')
              'cGxhaW4='
              
              > // DEPRECATED //
              > new Buffer(inBase64, 'base64').toString()
              'plain'
              > (node:1188987) [DEP0005] DeprecationWarning: Buffer() is deprecated due to security and usability issues. Please use the Buffer.alloc(), Buffer.allocUnsafe(), or Buffer.from() methods instead.
              (Use `node --trace-deprecation ...` to show where the warning was created)
              
              // Works //
              > Buffer.from(inBase64, 'base64').toString()
              'plain'
              

              【讨论】:

                猜你喜欢
                • 2019-12-17
                • 1970-01-01
                • 1970-01-01
                • 2014-12-01
                • 2023-04-04
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                相关资源
                最近更新 更多