简体   繁体   English

Javascript Base64解码失败

[英]Javascript Base64 decode fails

I need to decode some base64 encoded strings in Javascript. 我需要在Javascript中解码一些base64编码的字符串。 At the beginning, I was using atob() / btoa() functions. 开始时,我使用的是atob()/ btoa()函数。 But IE does not support those functions. 但是IE不支持这些功能。 So I chose to use a javascript library for that ( https://code.google.com/p/stringencoders/source/browse/trunk/javascript/base64.js ) 因此,我选择为此使用一个JavaScript库( https://code.google.com/p/stringencoders/source/browse/trunk/javascript/base64.js

If I try to decode the following string with btoa / atob , I don't have any problem (on chrome) But, when I try to decode with the base64 library, the operation fails. 如果我尝试使用btoa / atob解码以下字符串,则在chrome上没有任何问题,但是,当我尝试使用base64库进行解码时,该操作将失败。

Here is the chain I try to decode : 这是我尝试解码的链:

eyJpZHMiOlsiIiwiIiwiIiwiIiwiIiwiIiwiIiwiMTEiLCIiLCIxMSIsIiIsIiJdLCJkdXJhdGlvbnMiOlsiIiwiIiwiIiwiIiwiIiwiIiwiIiwiNyIsIiIsIjUiLCIiLCIiXSwic2xvdE51bWJlcnMiOlsiIiwiIiwiIiwiIiwiIiwiIiwiIiwiMjMiLCIiLCIzMSIsIiIsIiJdLCJwb3NpdGlvbnMiOlsiIiwiIiwiIiwiIiwiIiwiIiwiIiwiNyIsIiIsIjE1IiwiIiwiIl19

According to the base64 library's code, the string length must be a multiple of 4. In this case, the string length is 280. 280%4 = 0 so the decoding should not fail, but it does ! 根据base64库的代码,字符串长度必须为4的倍数。在这种情况下,字符串长度为280。280%4 = 0,因此解码不应失败,但确实会失败!

  • The string has been encoded with the same library. 该字符串已使用相同的库进行编码。

  • I have the same problem with other base64 libraries I found on internet 我在互联网上发现的其他base64库也存在相同的问题

What is wrong with this string ? 这个字符串怎么了? Why does the decoding fails with the library but not with the atob()'s chrome implementation ? 为什么解码在库中失败而在atob()的chrome实现中失败了?

Cheers, Steven 干杯,史蒂文

Try this library: http://jsbase64.codeplex.com/releases/view/89265 . 试试这个库: http : //jsbase64.codeplex.com/releases/view/89265 It is fast and seems to be reliable; 它很快,似乎很可靠; it actually has a test suite. 它实际上有一个测试套件。 I tested it in IE8 mode using the HTML below and it worked well. 我使用下面的HTML在IE8模式下对其进行了测试,并且效果很好。 I also created a JSBin (JSBin doesn't support IE8) with the library inlined here: http://jsbin.com/faxawa/1/edit?js,console . 我还创建了一个JSBin(JSBin不支持IE8),并在此内联了以下库: http ://jsbin.com/faxawa/1/edit?js,console。

There is also a long StackOverflow thread on various base64 libraries that is worth looking at here: Base64 encoding and decoding in client-side Javascript . 在各种base64库上还有一个长长的StackOverflow线程,值得在这里查看: 客户端Javascript中的Base64编码和解码

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

If you are using angular or nodeJs just do this: 如果您使用的是angularnodeJs ,请执行以下操作:

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

This serves as replacement for atob() method which is not supported in IE . 这可以替代IE不支持的atob()方法。 This works on almost all the browsers. 这几乎适用于所有浏览器。

Additionally if you want to create a blob out of the ByteArray, this is the way to go 此外,如果您想从ByteArray中创建一个Blob,这是可行的方法

let contentType = myBase64Url.split(';', 2)[0].split(':')[1];
var blob = new Blob([byteArray], {type: contentType });

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM