Base64 is a similar set of binary-to-text encoding rules that enable binary data to be represented in ASCII string format after being interpreted to the Radix 64 representation. The word Base64 comes from a MIME data transmission encoding.

The browser

Modern browsers natively support base64 codec, which can be used in both the console and JS worker. It provides two methods: ATob () btoa() for decoding and encoding, respectively.

btoa()

Creates a base-64 encoded ASCII String from a String object, where each character in the String is treated as a binary data byte.

Because this function treats each character as a byte of binary data, regardless of the actual number of bytes that make up the character, an InvalidCharacterError exception is raised if any character’s code point is outside the range 0x00 to 0xFF. See the Unicode_ string for an example that demonstrates how to encode a string containing characters with code points outside the range 0x00 to 0xFF.

Therefore, this function can only encode ASCLL strings in base64 format, and will report an error for strings other than ASCLL

The error message contains characters that are not encoded in latin1. These characters cannot be encoded.

Latin1: Latin-1 stands for ISO-8859-1. This character encoding only supports Unicode characters from U+0000 to U+00FF. Each character is encoded using a single byte. Characters outside this range are truncated and mapped to characters within this range.

The solution is to escape the non-ASCLL characters in the string and then encode them

// unicode to base64
function utoa(str) {
    return window.btoa(unescape(encodeURIComponent(str)));
}
Copy the code

The code above is derived from the MDN document WindowOrWorkerGlobalScope. Btoa ()

EncodeURIComponent is used to escape non-ASCLL characters in a string into a hexadecimal escape sequence in the format “% ASCII plus characters “, used in URI processing.

The processed string consists entirely of ASCLL characters, which are then converted by unescape() into a hexadecimal escape sequence, and then encoded into base64 by btoa(), but unescape() is not necessary because it is deprecated by the Web standard. The second is that the escaped string can already be encoded by btoA ().

function utoa(str) {
    return window.btoa(encodeURIComponent(str));
}
Copy the code

// unicode to base64 by 
function utoa(str) {
    return window.btoa(unescape(encodeURIComponent(str)));
}
// base64 to unicode
function atou(str) {
    return decodeURIComponent(escape(window.atob(str)));
}
Copy the code

atob()

As above, using atob() directly to convert a base64 string encoded from a string that does not consist entirely of ASCLL characters will result in the same error as above.

MDN document WindowOrWorkerGlobalScope. Btoa () method

// base64 to unicode
function atou(str) {
    return decodeURIComponent(escape(window.atob(str)));
}
Copy the code

Escape () is not necessary

function atou(str) {
    return decodeURIComponent(window.atob(str));
}
Copy the code

Polyfill

Many PC projects need to be compatible with IE9 and below, so we can introduce a ployfill script or a JS file specifically for these browsers.

Github.com/MaxArt2501/…

Another ployfill implementation

Github.com/davidchambe…

// Polyfill from https://github.com/MaxArt2501/base64-js/blob/master/base64.js
(function() {
    // base64 character set, plus padding character (=)
    var b64 = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=".// Regular expression to check formal correctness of base64 encoded strings
        b64re = / ^ (? :[A-Za-z\d+\/]{4})*? (? :[A-Za-z\d+\/]{2}(? : = =)? |[A-Za-z\d+\/]{3}=?) ? $/;

    window.btoa = window.btoa || function(string) {
        string = String(string);
        var bitmap, a, b, c,
            result = "",
            i = 0,
            rest = string.length % 3; // To determine the final padding

        for (; i < string.length;) {
            if ((a = string.charCodeAt(i++)) > 255 ||
                (b = string.charCodeAt(i++)) > 255 ||
                (c = string.charCodeAt(i++)) > 255)
                throw new TypeError("Failed to execute 'btoa' on 'Window': The string to be encoded contains characters outside of the Latin1 range.");

            bitmap = (a << 16) | (b << 8) | c;
            result += b64.charAt(bitmap >> 18 & 63) + b64.charAt(bitmap >> 12 & 63) +
                b64.charAt(bitmap >> 6 & 63) + b64.charAt(bitmap & 63);
        }

        // If there's need of padding, replace the last 'A's with equal signs
        return rest ? result.slice(0, rest - 3) + "= = =".substring(rest) : result;
    };

    window.atob = window.atob || function(string) {
        // atob can work with strings with whitespaces, even inside the encoded part,
        // but only \t, \n, \f, \r and ' ', which can be stripped.
        string = String(string).replace(/[\t\n\f\r ]+/g."");
        if(! b64re.test(string))throw new TypeError("Failed to execute 'atob' on 'Window': The string to be decoded is not correctly encoded.");

        // Adding the padding if missing, for semplicity
        string += "= =".slice(2 - (string.length & 3));
        var bitmap, result = "",
            r1, r2, i = 0;
        for (; i < string.length;) {
            bitmap = b64.indexOf(string.charAt(i++)) << 18 | b64.indexOf(string.charAt(i++)) << 12 |
                (r1 = b64.indexOf(string.charAt(i++))) << 6 | (r2 = b64.indexOf(string.charAt(i++)));

            result += r1 === 64 ? String.fromCharCode(bitmap >> 16 & 255) :
                r2 === 64 ? String.fromCharCode(bitmap >> 16 & 255, bitmap >> 8 & 255) :
                String.fromCharCode(bitmap >> 16 & 255, bitmap >> 8 & 255, bitmap & 255);
        }
        returnresult; }; }) ()Copy the code

Convert typed arrays to Base64

Sometimes the back end passes us a binary stream of file resources that we need to use a typed array to store and read.

Arraybuffers, called typed arrays, were created to solve a problem: manipulating binary data.

Binary data consisting only of zeros and ones is often very large. Thousands of bytes are not uncommon. Traditional arrays are very inefficient to handle binary data.

Let’s now initialize a buffer instance with new ArrayBuffer(10) and see what we get.

let buffer = new ArrayBuffer(10);
console.log(buffer);

ArrayBuffer(10) {}
[[Int8Array]] :Int8Array(10) [0.0.0.0.0.0.0.0.0.0]
[[Int16Array]] :Int16Array(5) [0.0.0.0.0]
[[Uint8Array]] :Uint8Array(10) [0.0.0.0.0.0.0.0.0.0]
byteLength: 10
__proto__: ArrayBuffer
Copy the code

As you can see, there are several views in the ArrayBuffer. Int8Array represents an array of 8-bit signed integers, Int16Array represents an array of 16-bit signed integers, and Uint8Array represents an array of 8-bit unsigned integers.

Of course, if we want to fetch Int8Array, for example, we can’t fetch it directly from buffer.int8Array. This is because the ArrayBuffer cannot be read or written directly by subscript, so we need to construct an array instance of the related type.

const myUint8Array = new Uint8Array(buffer)
Copy the code

Once you have the array value, how do you convert it to Base64? Simply use the string.fromCharCode function, which takes a sequence of code units as an argument and outputs a plain String. And the typed array that we just got is exactly where the code units are.

const myStr = String.fromCharCode(... myUint8Array)Copy the code

Now that the values in the type array are all converted to strings, we encode them into base64 strings using btoa()

node

Although the Node environment does not provide a special method for codec base64, we can easily do so using buffer.toString(), which is not only useful for processing strings, but also for processing files.

Processing strings

function stringToBase64(str){
    let base64Str = Buffer.from(str).toString('base64')
    return base64Str;
}

function base64ToString(base64Str){
    let str = Buffer.from(base64Str,'base64').toString()
    return str
}
Copy the code

Handle file

Take a chestnut

Base64 codec an image

/ / code
const fs = require('fs')
const fileToBase64  = fs.readFileSync('./img.png')
console.log(fileToBase64.toString('base64'))

/ / outputiVBORw0KGgoAAAANSUhEUgAAASwAAAEsCAYAAAB5fY51AAAgAElEQVR4Xuy9CZQdZ3Uu+tVcdeah5251t8bWZEuyJGxjecJDGHMJYEISwiPAu7DyXt66YSUv yc3wlEByIXkk910ePCC5gSQ3IYlJwg0EG4ONsS3Pkm1Jlq1Z6kE9nXmqU/Nbe1cdWZiEaAqms+p4tVtSV9X5z66/vt7Dt78tIH7FFogtEFtghVhAWCHrjJcZ WyC2QGwBxIAVb4LYArEFVowFYsBaMbcqXmhsgdgCMWDFeyC2QGyBFWOBGLBWzK2KFxpbILZADFjxHogtEFtgxVggBqwVc6vihcYWiC0QA1a8B2ILxBZYMRaI AWvF3Kp4obEFYgvEgBXvgdgCsQVWjAViwFoxtypeaGyB2AIxYMV7ILZAbIEVY4EYsFbMrYoXGlsgtkAMWPEeiC0QW2DFWCAGrBVzq+KFxhaILRADVrwHYgvE FlgxFogBa8XcqnihsQViC8SAFe.../ / decoding
const base64Tofile = Buffer.from(fileToBase64.toString('base64'),'base64')
// Output img2.png
fs.writeFileSync('img2.png', base64Tofile);
Copy the code

To be recognized by the browser, the encoded file must be prefixed according to its MIME type, such as PNG :data:image/ PNG; Base64,, TXT text :data:text/plain; base64,

Js – base64 library

Github.com/dankogai/js…

See the Github documentation for details, and it’s easy to use