JavaScript中是否有任何方法可以用来编码和解码使用base64编码的字符串?


当前回答

有人说code golf吗?=)

以下是我在跟上时代的同时提高我的障碍的尝试。提供给你方便。

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的$([])。每个方法的实现都是同步的。

如果你也有这样疯狂的想法,0延迟窗口。setTimeout将异步运行base64解码,并在完成时使用结果执行回调函数。

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

@牙刷建议“像数组一样索引字符串”,并取消分割。这个例行公事似乎真的很奇怪,不确定如何兼容它将,但它确实击中另一个小鸟,所以让我们有它。

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()如果你愿意,这应该给你带来一个问题。

ie.

return r.trimRight();

注意:

结果是一个ascii字节字符串,如果你需要unicode,最简单的是转义字节字符串,然后可以用decodeURIComponent解码产生unicode字符串。

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

由于转义已被弃用,我们可以将函数改为直接支持unicode,而不需要转义或string . 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);
  }));
}

nJoy !

其他回答

短而快速的Base64 JavaScript解码函数没有Failsafe:

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

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

结果,我在这里看到的所有脚本都将西里尔Base64转换为iso-8859-1编码。奇怪的是没有人注意到这一点。

因此,要恢复西里尔字母,只需将文本从iso-8859-1转换为windows-1251即可。

我认为其他语言也是如此。只要把Cyrilic window -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();

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

var base64 = 'SGVsbG8gV29ybGQ='
var base64_decode = new Buffer(base64, 'base64').toString('ascii');

console.log(base64_decode); // "Hello World"

以下是Sniper的文章的压缩版。它假定格式良好的base64字符串,没有回车。这个版本消除了几个循环,从Yaroslav中添加了&0xff修复,消除了尾随null,再加上一些代码golf。

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

函数b64_to_utf8(STR) { 返回decodeURIComponent(逃避(窗口。Atob (STR))); }

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