我有一个PHP脚本,可以将PNG图像编码为Base64字符串。

我想用JavaScript做同样的事情。我知道如何打开文件,但我不知道如何进行编码。我不习惯使用二进制数据。


当前回答

我需要一个UTF-8字符串编码为Base64为我的一个项目。这里的大多数答案似乎在转换为UTF-8时不能正确处理UTF-16代理对,因此,为了完成,我将发布我的解决方案:

function strToUTF8Base64(str) {

    function decodeSurrogatePair(hi, lo) {
        var resultChar = 0x010000;
        resultChar += lo - 0xDC00;
        resultChar += (hi - 0xD800) << 10;
        return resultChar;
    }

    var bytes = [0, 0, 0];
    var byteIndex = 0;
    var result = [];

    function output(s) {
        result.push(s);
    }

    function emitBase64() {

        var digits =
                'ABCDEFGHIJKLMNOPQRSTUVWXYZ' +
                'abcdefghijklmnopqrstuvwxyz' +
                '0123456789+/';

        function toDigit(value) {
            return digits[value];
        }

        // --Byte 0--    --Byte 1--    --Byte 2--
        // 1111  1122    2222  3333    3344  4444

        var d1 = toDigit(bytes[0] >> 2);
        var d2 = toDigit(
            ((bytes[0] & 0x03) << 4) |
            (bytes[1] >> 4));
        var d3 = toDigit(
            ((bytes[1] & 0x0F) << 2) |
            (bytes[2] >> 6));
        var d4 = toDigit(
            bytes[2] & 0x3F);

        if (byteIndex === 1) {
            output(d1 + d2 + '==');
        }
        else if (byteIndex === 2) {
            output(d1 + d2 + d3 + '=');
        }
        else {
            output(d1 + d2 + d3 + d4);
        }
    }

    function emit(chr) {
        bytes[byteIndex++] = chr;
        if (byteIndex == 3) {
            emitBase64();
            bytes[0] = 0;
            bytes[1] = 0;
            bytes[2] = 0;
            byteIndex = 0;
        }
    }

    function emitLast() {
        if (byteIndex > 0) {
            emitBase64();
        }
    }

    // Converts the string to UTF8:

    var i, chr;
    var hi, lo;
    for (i = 0; i < str.length; i++) {
        chr = str.charCodeAt(i);

        // Test and decode surrogate pairs in the string
        if (chr >= 0xD800 && chr <= 0xDBFF) {
            hi = chr;
            lo = str.charCodeAt(i + 1);
            if (lo >= 0xDC00 && lo <= 0xDFFF) {
                chr = decodeSurrogatePair(hi, lo);
                i++;
            }
        }

        // Encode the character as UTF-8.
        if (chr < 0x80) {
            emit(chr);
        }
        else if (chr < 0x0800) {
            emit((chr >> 6) | 0xC0);
            emit(((chr >> 0) & 0x3F) | 0x80);
        }
        else if (chr < 0x10000) {
            emit((chr >> 12) | 0xE0);
            emit(((chr >>  6) & 0x3F) | 0x80);
            emit(((chr >>  0) & 0x3F) | 0x80);
        }
        else if (chr < 0x110000) {
            emit((chr >> 18) | 0xF0);
            emit(((chr >> 12) & 0x3F) | 0x80);
            emit(((chr >>  6) & 0x3F) | 0x80);
            emit(((chr >>  0) & 0x3F) | 0x80);
        }
    }

    emitLast();

    return result.join('');
}

注意,代码没有经过彻底的测试。我测试了一些输入,包括strToUTF8Base64('衠衢蠩蠨'),并将其与在线编码工具(https://www.base64encode.org/)的输出进行了比较。

其他回答

如果有人想在Typescript中将一个字符串编码为base64

我调整了Peter Mortensen的答案并添加了类型(在需要的地方)

const Base64 = {


_keyStr: "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=",

// added type string to input
encode: function(input: string) {
    let output = "";
    let chr1, chr2, chr3, enc1, enc2, enc3, enc4;
    let i = 0;

    input = Base64._utf8_encode(input);

    while (i < input.length) {

        chr1 = input.charCodeAt(i++);
        chr2 = input.charCodeAt(i++);
        chr3 = input.charCodeAt(i++);

        enc1 = chr1 >> 2;
        enc2 = ((chr1 & 3) << 4) | (chr2 >> 4);
        enc3 = ((chr2 & 15) << 2) | (chr3 >> 6);
        enc4 = chr3 & 63;

        if (isNaN(chr2)) {
            enc3 = enc4 = 64;
        } else if (isNaN(chr3)) {
            enc4 = 64;
        }

        output = output + this._keyStr.charAt(enc1) + this._keyStr.charAt(enc2) + this._keyStr.charAt(enc3) + this._keyStr.charAt(enc4);

    }

    return output;
},
// added type string to input
_utf8_encode: function(input: string) {
    input= input.replace(/\r\n/g, "\n");
    let utftext = "";

    for (let n = 0; n < input.length; n++) {

        let c = input.charCodeAt(n);

        if (c < 128) {
            utftext += String.fromCharCode(c);
        }
        else if ((c > 127) && (c < 2048)) {
            utftext += String.fromCharCode((c >> 6) | 192);
            utftext += String.fromCharCode((c & 63) | 128);
        }
        else {
            utftext += String.fromCharCode((c >> 12) | 224);
            utftext += String.fromCharCode(((c >> 6) & 63) | 128);
            utftext += String.fromCharCode((c & 63) | 128);
        }

    }

    return utftext;
  },
}
 
// function that consumes that Base64.encode function
const encode = ( cipher : string) => {

  const encodedString: string = Base64.encode(cipher)

  return encodedString;
}

console.log(encode('Hello World!'))

JSFIDDLE 链接

请注意,这不适用于原始的Unicode字符串!请参阅这里的Unicode部分。

编码语法

var encodedData = window.btoa(stringToEncode);

解码语法

var decodedData = window.atob(encodedData);

对于更新的浏览器编码Uint8Array到字符串,并解码字符串到Uint8Array。

const base64 = {
    decode: s => Uint8Array.from(atob(s), c => c.charCodeAt(0)),
    encode: b => btoa(String.fromCharCode(...new Uint8Array(b)))
};

对于Node.js,你可以使用以下代码将string、Buffer或Uint8Array编码为string,并从string、Buffer或Uint8Array解码为Buffer。

const base64 = {
    decode: s => Buffer.from(s, 'base64'),
    encode: b => Buffer.from(b).toString('base64')
};

在_utf8_decode的两个实现中都有一些错误。C1和c2由于var语句的错误使用被赋值为全局变量,c3根本没有初始化或声明。

它可以工作,但这些变量将覆盖该函数之外的任何具有相同名称的现有变量。

这里有一个版本不会这样做:

// private method for UTF-8 decoding
_utf8_decode : function (utftext) {
    var string = "";
    var i = 0;
    var c = 0, c1 = 0, c2 = 0;

    while ( i < utftext.length ) {

        c = utftext.charCodeAt(i);

        if (c < 128) {
            string += String.fromCharCode(c);
            i++;
        }
        else if((c > 191) && (c < 224)) {
            c1 = utftext.charCodeAt(i+1);
            string += String.fromCharCode(((c & 31) << 6) | (c1 & 63));
            i += 2;
        }
        else {
            c1 = utftext.charCodeAt(i+1);
            c2 = utftext.charCodeAt(i+2);
            string += String.fromCharCode(((c & 15) << 12) | ((c1 & 63) << 6) | (c2 & 63));
            i += 3;
        }
    }
    return string;
}

如果你使用Node.js,你可以这样做:

let a = Buffer.from('JavaScript').toString('base64');
console.log(a);

let b = Buffer.from(a, 'base64').toString();
console.log(b);