Javascript Base64 解码失败

标签 javascript base64

我需要在 Javascript 中解码一些 base64 编码的字符串。 一开始,我使用 atob()/btoa() 函数。但IE不支持这些功能。所以我选择使用 javascript 库 (https://code.google.com/p/stringencoders/source/browse/trunk/javascript/base64.js)

如果我尝试使用 btoa/atob 解码以下字符串,我没有任何问题(在 chrome 上) 但是,当我尝试使用 Base64 库进行解码时,操作失败。

这是我尝试解码的链:

eyJpZHMiOlsiIiwiIiwiIiwiIiwiIiwiIiwiIiwiMTEiLCIiLCIxMSIsIiIsIiJdLCJkdXJhdGlvbnMiOlsiIiwiIiwiIiwiIiwiIiwiIiwiIiwiNyIsIiIsIjUiLCIiLCIiXSwic2xvdE51bWJlcnMiOlsiIiwiIiwiIiwiIiwiIiwiIiwiIiwiMjMiLCIiLCIzMSIsIiIsIiJdLCJwb3NpdGlvbnMiOlsiIiwiIiwiIiwiIiwiIiwiIiwiIiwiNyIsIiIsIjE1IiwiIiwiIl19

根据base64库的代码,字符串长度必须是4的倍数。在本例中,字符串长度为280。280%4 = 0,因此解码不应该失败,但确实失败了!

  • 该字符串已使用相同的库进行编码。

  • 我在互联网上找到的其他 Base64 库也有同样的问题

这个字符串有什么问题吗?为什么库的解码失败,而 atob() 的 chrome 实现却失败?

干杯, 史蒂文

最佳答案

尝试这个库:http://jsbase64.codeplex.com/releases/view/89265。它速度快而且看起来很可靠;它实际上有一个测试套件。我使用下面的 HTML 在 IE8 模式下测试了它,效果很好。我还创建了一个 JSBin(JSBin 不支持 IE8),其中内联了库: http://jsbin.com/faxawa/1/edit?js,console

在各种 Base64 库上还有一个很长的 StackOverflow 线程,值得一看:Base64 encoding and decoding in client-side Javascript

<!DOCTYPE html>
<html>
<head>
  <meta charset="utf-8">
  <title>JS Bin</title>    
</head>
<body>
    <script>
    /* B64 code from here: http://jsbase64.codeplex.com/releases/view/89265 */

/*
Copyright Vassilis Petroulias [DRDigit]

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

       http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
var B64 = {
    alphabet: 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=',
    lookup: null,
    ie: /MSIE /.test(navigator.userAgent),
    ieo: /MSIE [67]/.test(navigator.userAgent),
    encode: function (s) {
        var buffer = B64.toUtf8(s),
            position = -1,
            len = buffer.length,
            nan0, nan1, nan2, enc = [, , , ];
        if (B64.ie) {
            var result = [];
            while (++position < len) {
                nan0 = buffer[position];
                nan1 = buffer[++position];
                enc[0] = nan0 >> 2;
                enc[1] = ((nan0 & 3) << 4) | (nan1 >> 4);
                if (isNaN(nan1))
                    enc[2] = enc[3] = 64;
                else {
                    nan2 = buffer[++position];
                    enc[2] = ((nan1 & 15) << 2) | (nan2 >> 6);
                    enc[3] = (isNaN(nan2)) ? 64 : nan2 & 63;
                }
                result.push(B64.alphabet.charAt(enc[0]), B64.alphabet.charAt(enc[1]), B64.alphabet.charAt(enc[2]), B64.alphabet.charAt(enc[3]));
            }
            return result.join('');
        } else {
            var result = '';
            while (++position < len) {
                nan0 = buffer[position];
                nan1 = buffer[++position];
                enc[0] = nan0 >> 2;
                enc[1] = ((nan0 & 3) << 4) | (nan1 >> 4);
                if (isNaN(nan1))
                    enc[2] = enc[3] = 64;
                else {
                    nan2 = buffer[++position];
                    enc[2] = ((nan1 & 15) << 2) | (nan2 >> 6);
                    enc[3] = (isNaN(nan2)) ? 64 : nan2 & 63;
                }
                result += B64.alphabet[enc[0]] + B64.alphabet[enc[1]] + B64.alphabet[enc[2]] + B64.alphabet[enc[3]];
            }
            return result;
        }
    },
    decode: function (s) {
        if (s.length % 4)
            throw new Error("InvalidCharacterError: 'B64.decode' failed: The string to be decoded is not correctly encoded.");
        var buffer = B64.fromUtf8(s),
            position = 0,
            len = buffer.length;
        if (B64.ieo) {
            var result = [];
            while (position < len) {
                if (buffer[position] < 128) 
                    result.push(String.fromCharCode(buffer[position++]));
                else if (buffer[position] > 191 && buffer[position] < 224) 
                    result.push(String.fromCharCode(((buffer[position++] & 31) << 6) | (buffer[position++] & 63)));
                else 
                    result.push(String.fromCharCode(((buffer[position++] & 15) << 12) | ((buffer[position++] & 63) << 6) | (buffer[position++] & 63)));
            }
            return result.join('');
        } else {
            var result = '';
            while (position < len) {
                if (buffer[position] < 128) 
                    result += String.fromCharCode(buffer[position++]);
                else if (buffer[position] > 191 && buffer[position] < 224) 
                    result += String.fromCharCode(((buffer[position++] & 31) << 6) | (buffer[position++] & 63));
                else 
                    result += String.fromCharCode(((buffer[position++] & 15) << 12) | ((buffer[position++] & 63) << 6) | (buffer[position++] & 63));
            }
            return result;
        }
    },
    toUtf8: function (s) {
        var position = -1,
            len = s.length,
            chr, buffer = [];
        if (/^[\x00-\x7f]*$/.test(s)) while (++position < len)
            buffer.push(s.charCodeAt(position));
        else while (++position < len) {
            chr = s.charCodeAt(position);
            if (chr < 128) 
                buffer.push(chr);
            else if (chr < 2048) 
                buffer.push((chr >> 6) | 192, (chr & 63) | 128);
            else 
                buffer.push((chr >> 12) | 224, ((chr >> 6) & 63) | 128, (chr & 63) | 128);
        }
        return buffer;
    },
    fromUtf8: function (s) {
        var position = -1,
            len, buffer = [],
            enc = [, , , ];
        if (!B64.lookup) {
            len = B64.alphabet.length;
            B64.lookup = {};
            while (++position < len)
                B64.lookup[B64.alphabet.charAt(position)] = position;
            position = -1;
        }
        len = s.length;
        while (++position < len) {
            enc[0] = B64.lookup[s.charAt(position)];
            enc[1] = B64.lookup[s.charAt(++position)];
            buffer.push((enc[0] << 2) | (enc[1] >> 4));
            enc[2] = B64.lookup[s.charAt(++position)];
            if (enc[2] == 64) 
                break;
            buffer.push(((enc[1] & 15) << 4) | (enc[2] >> 2));
            enc[3] = B64.lookup[s.charAt(++position)];
            if (enc[3] == 64) 
                break;
            buffer.push(((enc[2] & 3) << 6) | enc[3]);
        }
        return buffer;
    }
};

var encoded = 'eyJpZHMiOlsiIiwiIiwiIiwiIiwiIiwiIiwiIiwiMTEiLCIiLCIxMSIsIiIsIiJdLCJkdXJhdGlvbnMiOlsiIiwiIiwiIiwiIiwiIiwiIiwiIiwiNyIsIiIsIjUiLCIiLCIiXSwic2xvdE51bWJlcnMiOlsiIiwiIiwiIiwiIiwiIiwiIiwiIiwiMjMiLCIiLCIzMSIsIiIsIiJdLCJwb3NpdGlvbnMiOlsiIiwiIiwiIiwiIiwiIiwiIiwiIiwiNyIsIiIsIjE1IiwiIiwiIl19';

var decodedNative = (typeof atob === 'function' ? atob(encoded) : undefined);
var decodedLibrary = B64.decode(encoded);

console.log(decodedNative);
console.log(decodedLibrary);
console.log('Match: ' + (decodedLibrary === decodedNative));
    </script>
</body>
</html>

关于Javascript Base64 解码失败,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24943255/

相关文章:

java - 如何在 JSON 中写入编码流并在 ajax 中检索回来?

c# - 解码 Base64 和 Inflate Zlib 压缩 XML

javascript - 用于并行加载依赖数据源的 Coffeescript/Javascript 设计模式

javascript - 多张图像上的 CSS 过渡

javascript - 如何在鼠标指针处打开 Kendo 窗口

javascript - 为什么悬停选择器不适用于类?

javascript - Angular Karma 测试无法正常运行,给出错误 "Argument ' fn' 不是函数,未定义”

javascript - 将 ImageData 对象(不是 Canvas )转换为图像数据 URL

ruby - 如何避免在解码文件时出现 UndefinedConversionError?

php - 如何在 yii 框架上将 blob 编码为 base64 字符串?