Javascript Base64解码失败

时间:2014-07-24 20:22:00

标签: 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实现?

干杯, 史蒂芬

2 个答案:

答案 0 :(得分:1)

试试这个图书馆: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>

答案 1 :(得分:0)

如果您使用angularnodeJs,请执行以下操作:

let b64Data = myBase64Url.split(',', 2)[1];
var byteArray = new Buffer(b64Data ,'base64');

这可以替代atob()IE不支持的let contentType = myBase64Url.split(';', 2)[0].split(':')[1]; var blob = new Blob([byteArray], {type: contentType }); 方法。这几乎适用于所有浏览器。

此外,如果你想用ByteArray创建一个blob,这是要走的路

'.string.html':
  'MAKE PAGE':
    'prefix': 'makepage'
    'body': '''
    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <meta content="width=device-width, initial-scale=1.0" name="viewport">
        <meta content="ie=edge" http-equiv="X-UA-Compatible">
        <link href="/assets/style.css" rel="stylesheet">
        <link href="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0/css/bootstrap.min.css" rel="stylesheet">
        <link href="/assets/hero.css" rel="stylesheet">
        <script defer src="https://use.fontawesome.com/releases/v5.0.6/js/all.js">
        </script>
        <title></title>
    </head>
    <body>
        <nav class="navbar navbar-expand-lg navbar-dark bg-primary fixed-top">
        <div class="container">
          <a class="navbar-brand" href="http://jackspangenberg.com/">
            <img src="/assets/logo_white.png" style="max-height: 40px;" alt="">
          </a>
          <button class="navbar-toggler" type="button" data-toggle="collapse" data-target="#navbarTogglerDemo02" aria-controls="navbarTogglerDemo02" aria-expanded="false" aria-label="Toggle navigation">
            <span class="navbar-toggler-icon"></span>
          </button>
          </div>
        </div>
      </nav>
        <br>
        <br>
        <section class="hero is-medium is-primary is-bold mx-0">
            <div class="hero-body mx-0">
                <div class="container">
                    <h1 class="display-3 cushycms">Page Name</h1>
                    <br>
                </div>
            </div>
        </section>
        <nav aria-label="breadcrumb">
            <div class="container">
                <ol class="breadcrumb">
                    <li class="breadcrumb-item">
                        <a href="/index.php">Home</a>
                    </li>
                    <li class="breadcrumb-item active">Page Name</li>
                </ol>
            </div>
        </nav>





        <script src="https://code.jquery.com/jquery-3.2.1.slim.min.js">
        </script>
        <script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.12.9/umd/popper.min.js">
        </script>
        <script src="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0/js/bootstrap.min.js">
        </script>
        <script src="https://unpkg.com/scrollreveal/dist/scrollreveal.min.js">
        </script>
    </body>
    </html>
    '''