Come puoi codificare una stringa in Base64 in JavaScript?


810

Ho uno script PHP che può codificare un'immagine PNG in una stringa Base64.

Mi piacerebbe fare la stessa cosa usando JavaScript. So come aprire i file, ma non sono sicuro di come eseguire la codifica. Non sono abituato a lavorare con i dati binari.


2
Ecco il modo migliore per base64_encode e base64_decode utilizzando javascript. Vedi sotto i collegamenti. phpjs.org/functions/base64_encode:358 phpjs.org/functions/base64_decode:357
gautamlakum

ecco un altro plugin jquery per codifica / decodifica base64
zahid9i

Controlla microjs: microjs.com/#base64
Vinod Srivastav

Risposte:


866

È possibile utilizzare btoa()e atob()per convertire da e verso la codifica base64.

Sembra esserci un po 'di confusione nei commenti su ciò che queste funzioni accettano / restituiscono, quindi ...

  • btoa()accetta una "stringa" in cui ogni carattere rappresenta un byte a 8 bit - se si passa una stringa contenente caratteri che non possono essere rappresentati in 8 bit, probabilmente si interromperà . Questo non è un problema se in realtà stai trattando la stringa come un array di byte, ma se stai provando a fare qualcos'altro, dovrai prima codificarla.

  • atob()restituisce una "stringa" in cui ogni carattere rappresenta un byte a 8 bit, ovvero il suo valore sarà compreso tra 0e 0xff. Questo non significa che sia ASCII - presumibilmente se stai usando questa funzione, ti aspetti di lavorare con i dati binari e non con il testo.

Guarda anche:


47
Nota che questo funziona anche con i browser webkit, come Safari.
Daniel Von Fange,

5
ma non funziona su iPhone3G con iOS 4.1. Funziona sul simulatore simulatore iPhone quando impostato su iPhone4 o iPhone.
Concedi il

29
Si noti la considerazione speciale per le stringhe Unicode: developer.mozilla.org/En/DOM/Window.btoa#Unicode_Strings btoa e atob funzionano correttamente solo per stringhe basate su ASCII. Come americano, probabilmente non noterai alcuna differenza ... ma la prima volta che usi un carattere accentato, il tuo codice si romperà.
Dan Esparza,

70
dovresti usare btoa(unescape(encodeURIComponent(str))))se str è UFT8
SET

4
Vedi la mia modifica, @Triynko. Questi non sono destinati ad essere utilizzati per elaborare testo , punto.
Shog9

289

Da qui :

/**
*
*  Base64 encode / decode
*  http://www.webtoolkit.info/
*
**/
var Base64 = {

// private property
_keyStr : "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=",

// public method for encoding
encode : function (input) {
    var output = "";
    var chr1, chr2, chr3, enc1, enc2, enc3, enc4;
    var 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;
},

// public method for decoding
decode : function (input) {
    var output = "";
    var chr1, chr2, chr3;
    var enc1, enc2, enc3, enc4;
    var i = 0;

    input = input.replace(/[^A-Za-z0-9\+\/\=]/g, "");

    while (i < input.length) {

        enc1 = this._keyStr.indexOf(input.charAt(i++));
        enc2 = this._keyStr.indexOf(input.charAt(i++));
        enc3 = this._keyStr.indexOf(input.charAt(i++));
        enc4 = this._keyStr.indexOf(input.charAt(i++));

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

        output = output + String.fromCharCode(chr1);

        if (enc3 != 64) {
            output = output + String.fromCharCode(chr2);
        }
        if (enc4 != 64) {
            output = output + String.fromCharCode(chr3);
        }

    }

    output = Base64._utf8_decode(output);

    return output;

},

// private method for UTF-8 encoding
_utf8_encode : function (string) {
    string = string.replace(/\r\n/g,"\n");
    var utftext = "";

    for (var n = 0; n < string.length; n++) {

        var c = string.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;
},

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

    while ( i < utftext.length ) {

        c = utftext.charCodeAt(i);

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

    }

    return string;
}

}

Inoltre, la ricerca su "codifica javascript base64" trasforma molte altre opzioni, di cui sopra è stata la prima.


3
Ciò è utile anche quando la codifica base64 non è standard; nel mio caso il carattere "/" non è stato usato e il "?" invece è stato usato il carattere, il che significa che anche in Chrome atob () non avrebbe decodificato le stringhe base64 in arrivo.
Chris Moschini,

21
Fai attenzione con questo codice: tenta di interpretare la tua stringa come una stringa codificata UTF-8. Abbiamo avuto un caso in cui avevamo una stringa binaria (cioè ogni carattere nella stringa doveva essere interpretato come un byte) e questo codice corrompeva i dati. Leggi la fonte, Luke.
Daniel Yankowsky,

11
Tutto ciò che è necessario per renderlo sicuro per la maggior parte della codifica / decodifica binaria per rimuovere l' string = string.replace(/\r\n/g,"\n");istruzione discutibile nel metodo di codifica utf8.
Marius,

7
@Marius: mi chiedo perché dovrebbero anche includere, string = string.replace(/\r\n/g,"\n");in primo luogo, lol. È come "oh, consente di codificare questa stringa, ma prima, perché non normalizziamo casualmente tutte le interruzioni di riga senza una buona ragione". Questo dovrebbe assolutamente essere rimosso dalla classe in ogni circostanza.
Triynko,

2
Non sono un guru javascript, ma questo codice sembra contenere un bug: se chr2 è NaN, il suo valore è ancora usato nell'istruzione enc2 = ((chr1 & 3) << 4) | (chr2 >> 4);. Nel mio browser funziona bene, è NaN>>4uguale a 0, ma non so se tutti i browser lo facciano (anche NaN/16uguale a NaN).
Jan

117

Internet Explorer 10+

// Define the string
var string = 'Hello World!';

// Encode the String
var encodedString = btoa(string);
console.log(encodedString); // Outputs: "SGVsbG8gV29ybGQh"

// Decode the String
var decodedString = atob(encodedString);
console.log(decodedString); // Outputs: "Hello World!"

Cross-Browser

// Create Base64 Object
var Base64={_keyStr:"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=",encode:function(e){var t="";var n,r,i,s,o,u,a;var f=0;e=Base64._utf8_encode(e);while(f<e.length){n=e.charCodeAt(f++);r=e.charCodeAt(f++);i=e.charCodeAt(f++);s=n>>2;o=(n&3)<<4|r>>4;u=(r&15)<<2|i>>6;a=i&63;if(isNaN(r)){u=a=64}else if(isNaN(i)){a=64}t=t+this._keyStr.charAt(s)+this._keyStr.charAt(o)+this._keyStr.charAt(u)+this._keyStr.charAt(a)}return t},decode:function(e){var t="";var n,r,i;var s,o,u,a;var f=0;e=e.replace(/[^A-Za-z0-9\+\/\=]/g,"");while(f<e.length){s=this._keyStr.indexOf(e.charAt(f++));o=this._keyStr.indexOf(e.charAt(f++));u=this._keyStr.indexOf(e.charAt(f++));a=this._keyStr.indexOf(e.charAt(f++));n=s<<2|o>>4;r=(o&15)<<4|u>>2;i=(u&3)<<6|a;t=t+String.fromCharCode(n);if(u!=64){t=t+String.fromCharCode(r)}if(a!=64){t=t+String.fromCharCode(i)}}t=Base64._utf8_decode(t);return t},_utf8_encode:function(e){e=e.replace(/\r\n/g,"\n");var t="";for(var n=0;n<e.length;n++){var r=e.charCodeAt(n);if(r<128){t+=String.fromCharCode(r)}else if(r>127&&r<2048){t+=String.fromCharCode(r>>6|192);t+=String.fromCharCode(r&63|128)}else{t+=String.fromCharCode(r>>12|224);t+=String.fromCharCode(r>>6&63|128);t+=String.fromCharCode(r&63|128)}}return t},_utf8_decode:function(e){var t="";var n=0;var r=c1=c2=0;while(n<e.length){r=e.charCodeAt(n);if(r<128){t+=String.fromCharCode(r);n++}else if(r>191&&r<224){c2=e.charCodeAt(n+1);t+=String.fromCharCode((r&31)<<6|c2&63);n+=2}else{c2=e.charCodeAt(n+1);c3=e.charCodeAt(n+2);t+=String.fromCharCode((r&15)<<12|(c2&63)<<6|c3&63);n+=3}}return t}}

// Define the string
var string = 'Hello World!';

// Encode the String
var encodedString = Base64.encode(string);
console.log(encodedString); // Outputs: "SGVsbG8gV29ybGQh"

// Decode the String
var decodedString = Base64.decode(encodedString);
console.log(decodedString); // Outputs: "Hello World!"

jsFiddle


con Node.js

Ecco come codificare il testo normale in base64 in Node.js:

//Buffer() requires a number, array or string as the first parameter, and an optional encoding type as the second parameter. 
// Default is utf8, possible encoding types are ascii, utf8, ucs2, base64, binary, and hex
var b = new Buffer('JavaScript');
// If we don't use toString(), JavaScript assumes we want to convert the object to utf8.
// We can make it convert to other formats by passing the encoding type to toString().
var s = b.toString('base64');

Ed ecco come decodificare le stringhe codificate in base64:

var b = new Buffer('SmF2YVNjcmlwdA==', 'base64')
var s = b.toString();

con Dojo.js

Per codificare una matrice di byte usando dojox.encoding.base64:

var str = dojox.encoding.base64.encode(myByteArray);

Per decodificare una stringa codificata in base64:

var bytes = dojox.encoding.base64.decode(str)

bower install angular-base64

<script src="bower_components/angular-base64/angular-base64.js"></script>

angular
    .module('myApp', ['base64'])
    .controller('myController', [

    '$base64', '$scope', 
    function($base64, $scope) {

        $scope.encoded = $base64.encode('a string');
        $scope.decoded = $base64.decode('YSBzdHJpbmc=');
}]);

3
Questa risposta si basa sul codice originale e NON include gli aggiornamenti a quel codice pubblicati in altre risposte qui.
Eugene Ryabtsev,

La soluzione NodeJS proposta è obsoleta.
Vladimir Nul,

94

Il codice di Sunny è eccezionale, tranne che si rompe in IE7 a causa dei riferimenti a "questo". Risolto sostituendo tali riferimenti con "Base64":

var Base64 = {
// private property
_keyStr : "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=",

// public method for encoding
encode : function (input) {
    var output = "";
    var chr1, chr2, chr3, enc1, enc2, enc3, enc4;
    var 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 +
        Base64._keyStr.charAt(enc1) + Base64._keyStr.charAt(enc2) +
        Base64._keyStr.charAt(enc3) + Base64._keyStr.charAt(enc4);

    }

    return output;
},

// public method for decoding
decode : function (input) {
    var output = "";
    var chr1, chr2, chr3;
    var enc1, enc2, enc3, enc4;
    var i = 0;

    input = input.replace(/[^A-Za-z0-9\+\/\=]/g, "");

    while (i < input.length) {

        enc1 = Base64._keyStr.indexOf(input.charAt(i++));
        enc2 = Base64._keyStr.indexOf(input.charAt(i++));
        enc3 = Base64._keyStr.indexOf(input.charAt(i++));
        enc4 = Base64._keyStr.indexOf(input.charAt(i++));

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

        output = output + String.fromCharCode(chr1);

        if (enc3 != 64) {
            output = output + String.fromCharCode(chr2);
        }
        if (enc4 != 64) {
            output = output + String.fromCharCode(chr3);
        }

    }

    output = Base64._utf8_decode(output);

    return output;

},

// private method for UTF-8 encoding
_utf8_encode : function (string) {
    string = string.replace(/\r\n/g,"\n");
    var utftext = "";

    for (var n = 0; n < string.length; n++) {

        var c = string.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;
},

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

    while ( i < utftext.length ) {

        c = utftext.charCodeAt(i);

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

    }
    return string;
}
}

4
ooh mio male, stavo prendendo l'input dall'URL del browser; dove | viene convertito in% 7C; quindi anche la codifica è errata.
Kanagavelu Sugumar,

So che questo è davvero vecchio, ma ho visto questa funzione usata in più di un posto, la stringa di chiave è in realtà a 65 caratteri, non 64. La stringa non è una specifica standard, non sono sicuro che sia importante, ma mi stavo solo chiedendo se lo fa?
Jonathan Wagner,

"usa rigoroso"; è ciò che rompe "questo" e altri elementi di tipo come "con" e da quello che ho letto, "eval" riceve un colpo di grazia. Tutte le idee fuori luogo sull'abuso. Personalmente non vedo perché JavaScript abbia bisogno di percorrere la sua strada, non è mai stato pensato per essere un programma strettamente legato e reso più complesso di quanto non sia già. Se vuoi essere associato, crea un compilatore per javascript.
Mark Giblin,

Tento di utilizzare questa funzione e ricevo l'errore: Causato da: org.mozilla.javascript.EcmaError: TypeError: Impossibile trovare la funzione Sostituisci nell'oggetto teste teste teste Sto cercando di codificare .txt con "teste teste teste". Qualcuno sa perché questo errore?
PRVS,

@JonathanWagner - ci sono 64 caratteri usati per la codifica normale. Il 65 ° carattere viene usato come riempimento per loro la stringa di input non ha un numero di caratteri divisibili per 3.
Kickstart

90

È possibile utilizzare btoa(da base-64) e atob(da base-64).

Per IE 9 e versioni precedenti, prova il plug -in jquery-base64 :

$.base64.encode("this is a test");
$.base64.decode("dGhpcyBpcyBhIHRlc3Q=");

133
Perché tutto deve essere un plug-in jQuery: c questa è solo la funzionalità JavaScript di base che non ha nulla a che fare con il DOM o jQuery
EaterOfCode

38
Questa non è una funzionalità di base o non ci sarebbero tante risposte diverse votate (incluso il codice fai-da-te tl; dr). Quindi, imho questo è in realtà un buon caso d'uso per jQuery (un liner, dovrebbe funzionare anche nel WebView di Android) - ancora di più se è già una dipendenza.
Risadinha,

1
Mi piace installare frammenti di codice come questo in jQuery principalmente perché esisteranno in uno spazio dei nomi controllato. Se non stai usando AMD o CommonJS o un modello di progettazione simile, è facile che il tuo spazio dei nomi globale diventi davvero disordinato con un sacco di funzioni casuali.
Sffc,

9
@Risadinha - tranne per il fatto che la sua funzionalità non dipende o estende affatto nulla di jQuery ... letteralmente i soli riferimenti a jQuery nel suo codice lo stanno collegando all'oggetto jQuery ... quindi qual è il punto di collegarlo a jQuery e quindi richiedere jQuery da usare? Basta crearne uno proprio base64.encode(...)e base64.decode(...)... collegarlo a jQuery quando ha zero funzionalità specifiche di jQuery non ha assolutamente senso ...
Jimbo Jonny

1
jQuery non è stato richiesto. Non è una risposta valida a una semplice vecchia domanda di JS.
metaColin

34

Dai commenti (di SET e Stefan Steiger) sotto la risposta accettata, ecco un breve riassunto di come codificare / decodificare una stringa da / verso base64 senza bisogno di una libreria.

str = "The quick brown fox jumps over the lazy dog";
b64 = btoa(unescape(encodeURIComponent(str)));
str = decodeURIComponent(escape(window.atob(b64)));

dimostrazione

(utilizza la libreria jQuery, ma non per codificare / decodificare)


Per confermare, questo supporta i caratteri UTF-8?
Crashalot,

1
@Crashalot Mi rendo conto che è troppo tardi di due anni, ma sì. Mi sto anche rendendo conto mentre scrivo che hai fornito una modifica che probabilmente ha fatto funzionare UTF8.
tycrek,

Per chiunque sia alla ricerca di una buona soluzione da utilizzare con Node.js, posso confermare che funziona. Per la decodifica in Nodo, ho usato:Buffer.from(b64data, 'base64').toString();
tycrek il

26

Ci sono un paio di bug in entrambe le implementazioni di _utf8_decode. c1e c2sono assegnati come variabili globali a causa dell'uso non corretto dell'istruzione vare c3non è affatto inizializzato o dichiarato.

Funziona, ma queste variabili sovrascriveranno quelle esistenti con lo stesso nome al di fuori di questa funzione.

Ecco una versione che non lo farà:

// 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;
}

9
@Daan Non avevo abbastanza rappresentante per modificare le risposte quando ho scritto questa risposta ... nel 2011.
ruba il

2
IE7? immagino che dovremmo smettere di perdere tempo a scrivere codice per questo, le persone non smetteranno di usare questa vecchia tecnologia a meno che noi sviluppatori non li abbiamo costretti a farlo!
Rami Dabain,

@RonanDejhero non funziona in IE7? Non ricordo se ho provato in quel particolare browser.
deruba l'

1
Cosa intendevo dire che se non funziona in IE7, a nessuno dovrebbe importare !. non ho provato e non lo
testerò

16

Ho + ottenuto la risposta di Sunny, ma volevo contribuire con alcune modifiche apportate al mio progetto nel caso qualcuno lo trovasse utile. Fondamentalmente ho appena ripulito un po 'il codice originale, quindi JSLint non si lamenta tanto e ho reso i metodi contrassegnati come privati ​​nei commenti in realtà privati. Ho anche aggiunto due metodi di cui avevo bisogno nel mio progetto, vale a dire decodeToHexe encodeFromHex.

Il codice:

var Base64 = (function() {
    "use strict";

    var _keyStr = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=";

    var _utf8_encode = function (string) {

        var utftext = "", c, n;

        string = string.replace(/\r\n/g,"\n");

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

            c = string.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;
    };

    var _utf8_decode = function (utftext) {
        var string = "", i = 0, 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;
    };

    var _hexEncode = function(input) {
        var output = '', i;

        for(i = 0; i < input.length; i++) {
            output += input.charCodeAt(i).toString(16);
        }

        return output;
    };

    var _hexDecode = function(input) {
        var output = '', i;

        if(input.length % 2 > 0) {
            input = '0' + input;
        }

        for(i = 0; i < input.length; i = i + 2) {
            output += String.fromCharCode(parseInt(input.charAt(i) + input.charAt(i + 1), 16));
        }

        return output;
    };

    var encode = function (input) {
        var output = "", chr1, chr2, chr3, enc1, enc2, enc3, enc4, i = 0;

        input = _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 += _keyStr.charAt(enc1);
            output += _keyStr.charAt(enc2);
            output += _keyStr.charAt(enc3);
            output += _keyStr.charAt(enc4);

        }

        return output;
    };

    var decode = function (input) {
        var output = "", chr1, chr2, chr3, enc1, enc2, enc3, enc4, i = 0;

        input = input.replace(/[^A-Za-z0-9\+\/\=]/g, "");

        while (i < input.length) {

            enc1 = _keyStr.indexOf(input.charAt(i++));
            enc2 = _keyStr.indexOf(input.charAt(i++));
            enc3 = _keyStr.indexOf(input.charAt(i++));
            enc4 = _keyStr.indexOf(input.charAt(i++));

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

            output += String.fromCharCode(chr1);

            if (enc3 !== 64) {
                output += String.fromCharCode(chr2);
            }
            if (enc4 !== 64) {
                output += String.fromCharCode(chr3);
            }

        }

        return _utf8_decode(output);
    };

    var decodeToHex = function(input) {
        return _hexEncode(decode(input));
    };

    var encodeFromHex = function(input) {
        return encode(_hexDecode(input));
    };

    return {
        'encode': encode,
        'decode': decode,
        'decodeToHex': decodeToHex,
        'encodeFromHex': encodeFromHex
    };
}());

Inizialmente pensavo che lo srotolamento della concatenazione dell'output in istruzioni separate sarebbe stato più ottimale, ma dopo averci pensato per un secondo, questo dovrebbe essere più inefficiente poiché le stringhe Javascript sono immutabili e causerebbe 4 copie di BLOB di dati potenzialmente enormi quando si lavora con file di dati binari di grandi dimensioni. È una scommessa più sicura concatenare prima i 4 caratteri e poi costruire una nuova stringa. Vorrei sapere con certezza un metodo di costruzione di stringhe migliore che sarebbe sicuramente efficace su tutte le piattaforme. (anche IE6)
Marius

Non ho preso in considerazione le prestazioni durante la pulizia del codice pubblicato in origine. L'ho appena reso più leggibile e reso i metodi contrassegnati come privati ​​nei commenti nell'originale in realtà sono privati ​​usando il modello del modulo rivelatore. Sono sicuro che può essere ottimizzato anche per quanto riguarda le prestazioni. Non sono del tutto sicuro quando la garbage collection entrerebbe in gioco qui e l'hashing di file di grandi dimensioni tramite Javascript non è molto comune (o probabilmente probabilmente non è la soluzione ottimale in ogni caso).
Joe Dyndale,

Divertente come questo codice vive qui. Ci sono già 3 diverse versioni in questa pagina.
Gregn3

16

Per i browser più recenti codificare Uint8Array su stringa e decodificare la stringa su Uint8Array.

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

Per Node.js è possibile utilizzare quanto segue per codificare string, Buffer o Uint8Array in string e decodificare da string, Buffer o Uint8Array in Buffer.

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

13

Per rendere amichevole un URL String con codifica Base64, in JavaScript potresti fare qualcosa del genere:

// if this is your Base64 encoded string
var str = 'VGhpcyBpcyBhbiBhd2Vzb21lIHNjcmlwdA=='; 

// make URL friendly:
str = str.replace(/\+/g, '-').replace(/\//g, '_').replace(/\=+$/, '');

// reverse to original encoding
str = (str + '===').slice(0, str.length + (str.length % 4));
str = str.replace(/-/g, '+').replace(/_/g, '/');

Vedi anche questo violino: http://jsfiddle.net/magikMaker/7bjaT/


9
Vorrei suggerire umilmente che l'uso di encodeURIComponentpotrebbe comportare un risultato superiore con minori spese di sforzo da parte dello sviluppatore.
Pablo Fernandez,

11
encodeURIComponent modificherà la lunghezza delle stringhe codificate in base64 e la sostituzione di '-' e '_' con '+' e '/' è pratica standard quando si utilizza base64 negli URL (ad es. docs.python.org/library/base64.html#base64 .urlsafe_b64encode ). Non c'è bisogno di arrabbiarsi.
natevw,

12

Nota che questo non è adatto per stringhe Unicode non elaborate! Vedi la sezione Unicode qui .

Sintassi per la codifica

var encodedData = window.btoa(stringToEncode);

Sintassi per la decodifica

var decodedData = window.atob(encodedData);


1
Link diretto alla sezione Unicode: developer.mozilla.org/en-US/docs/Web/API/…
TomTasche

12

Ho riscritto a mano questi metodi di codifica e decodifica, ad eccezione di quello esadecimale, in un formato modulare per la compatibilità multipiattaforma / browser e anche con reale ambito privato, e usi btoae atobse esistono a causa della velocità anziché dell'utilizzo la sua codifica:

https://gist.github.com/Nijikokun/5192472

Uso:

base64.encode(/* String */);
base64.decode(/* String */);

utf8.encode(/* String */);
utf8.decode(/* String */);

12

Questa domanda e le sue risposte mi hanno indicato la giusta direzione.
Soprattutto con unicode atob e btoa non si può usare "vaniglia" e oggigiorno TUTTO è unicode.

Direttamente da Mozilla, due belle funzioni per questo scopo (testate con tag unicode e html all'interno)

function b64EncodeUnicode(str) {
    return btoa(encodeURIComponent(str).replace(/%([0-9A-F]{2})/g, function(match, p1) {
        return String.fromCharCode('0x' + p1);
    }));
}

b64EncodeUnicode('✓ à la mode'); // "4pyTIMOgIGxhIG1vZGU="
b64EncodeUnicode('\n'); // "Cg=="



function b64DecodeUnicode(str) {
    return decodeURIComponent(Array.prototype.map.call(atob(str), function(c) {
        return '%' + ('00' + c.charCodeAt(0).toString(16)).slice(-2);
    }).join(''));
}

b64DecodeUnicode('4pyTIMOgIGxhIG1vZGU='); // "✓ à la mode"
b64DecodeUnicode('Cg=='); // "\n"

Queste funzioni eseguiranno un fulmineo rispetto alla decodifica raw base64 usando una funzione javascript personalizzata poiché btoa e atob vengono eseguiti all'esterno dell'interprete.

Se riesci a ignorare IE vecchio e vecchi telefoni cellulari (come iPhone 3?) Questa dovrebbe essere una buona soluzione.


10

se devi codificare un oggetto immagine HTML, puoi scrivere semplici funzioni come:

function getBase64Image(img) {  
  var canvas = document.createElement("canvas");  
  canvas.width = img.width;  
  canvas.height = img.height;  
  var ctx = canvas.getContext("2d");  
  ctx.drawImage(img, 0, 0);  
  var dataURL = canvas.toDataURL("image/png");  
  // escape data:image prefix
  return dataURL.replace(/^data:image\/(png|jpg);base64,/, "");  
  // or just return dataURL
  // return dataURL
}  

Per ottenere base64 di immagine per ID:

function getBase64ImageById(id){  
  return getBase64Image(document.getElementById(id));  
} 

di più qui


Sì, e var img = new Image (); img.src = "../images/myPic.png";
pdschuller,

7

Contribuire con un polyfill minimizzato per window.atob+ window.btoache sto attualmente utilizzando.

(function(){function t(t){this.message=t}var e="undefined"!=typeof exports?exports:this,r="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=";t.prototype=Error(),t.prototype.name="InvalidCharacterError",e.btoa||(e.btoa=function(e){for(var o,n,a=0,i=r,c="";e.charAt(0|a)||(i="=",a%1);c+=i.charAt(63&o>>8-8*(a%1))){if(n=e.charCodeAt(a+=.75),n>255)throw new t("'btoa' failed: The string to be encoded contains characters outside of the Latin1 range.");o=o<<8|n}return c}),e.atob||(e.atob=function(e){if(e=e.replace(/=+$/,""),1==e.length%4)throw new t("'atob' failed: The string to be decoded is not correctly encoded.");for(var o,n,a=0,i=0,c="";n=e.charAt(i++);~n&&(o=a%4?64*o+n:n,a++%4)?c+=String.fromCharCode(255&o>>(6&-2*a)):0)n=r.indexOf(n);return c})})();

6

Preferirei usare i metodi di codifica / decodifica bas64 di CryptoJS , la libreria più popolare per algoritmi crittografici standard e sicuri implementati in JavaScript usando le migliori pratiche e schemi.


6

Ecco una versione di AngularJS Factory di quella di @ user850789:

'use strict';

var ProjectNameBase64Factory = angular.module('project_name.factories.base64', []);

ProjectNameBase64Factory.factory('Base64', function () {
    var Base64 = {
        // private property
        _keyStr: "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=",

        // public method for encoding
        encode: function (input) {
            var output = "";
            var chr1, chr2, chr3, enc1, enc2, enc3, enc4;
            var 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 +
                         Base64._keyStr.charAt(enc1) + Base64._keyStr.charAt(enc2) +
                         Base64._keyStr.charAt(enc3) + Base64._keyStr.charAt(enc4);

            }

            return output;
        },

        // public method for decoding
        decode: function (input) {
            var output = "";
            var chr1, chr2, chr3;
            var enc1, enc2, enc3, enc4;
            var i = 0;

            input = input.replace(/[^A-Za-z0-9\+\/\=]/g, "");

            while (i < input.length) {

                enc1 = Base64._keyStr.indexOf(input.charAt(i++));
                enc2 = Base64._keyStr.indexOf(input.charAt(i++));
                enc3 = Base64._keyStr.indexOf(input.charAt(i++));
                enc4 = Base64._keyStr.indexOf(input.charAt(i++));

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

                output = output + String.fromCharCode(chr1);

                if (enc3 != 64) {
                    output = output + String.fromCharCode(chr2);
                }
                if (enc4 != 64) {
                    output = output + String.fromCharCode(chr3);
                }

            }

            output = Base64._utf8_decode(output);

            return output;

        },

        // private method for UTF-8 encoding
        _utf8_encode: function (string) {
            string = string.replace(/\r\n/g, "\n");
            var utftext = "";

            for (var n = 0; n < string.length; n++) {

                var c = string.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;
        },

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

            while (i < utftext.length) {

                c = utftext.charCodeAt(i);

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

            }
            return string;
        }
    };
    return Base64;
});

6

Avevo bisogno della codifica di una stringa UTF-8 come base64 per un mio progetto. La maggior parte delle risposte qui non sembrano gestire correttamente coppie surrogate UTF-16 durante la conversione in UTF-8, quindi, per amor di completamento, posterò la mia soluzione:

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('');
}

Si noti che il codice non è stato testato a fondo. Ho testato alcuni input, tra cui cose simili strToUTF8Base64('衠衢蠩蠨')e confrontati con l'output di uno strumento di codifica online ( https://www.base64encode.org/ ).


5

Per il mio progetto ho ancora bisogno di supportare IE7 e lavorare con input di grandi dimensioni per codificare.

Basato sul codice proposto da Joe Dyndale e come suggerito nel commento di Marius, è possibile migliorare le prestazioni con IE7 costruendo il risultato con un array anziché una stringa.

Ecco l'esempio per la codifica:

var encode = function (input) {
    var output = [], chr1, chr2, chr3, enc1, enc2, enc3, enc4, i = 0;

    input = _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.push(_keyStr.charAt(enc1));
        output.push(_keyStr.charAt(enc2));
        output.push(_keyStr.charAt(enc3));
        output.push(_keyStr.charAt(enc4));

    }

    return output.join("");
};

5

Mentre un po 'più di lavoro, se vuoi una soluzione nativa ad alte prestazioni ci sono alcune funzioni HTML5 che puoi usare.

Se riesci a ottenere i tuoi dati in a Blob, puoi usare la funzione FileReader.readAsDataURL () per ottenere un data://URL e tagliare la parte anteriore per ottenere i dati base64.

Tuttavia, potresti dover eseguire ulteriori elaborazioni per codificare i dati, poiché non sono sicuro che i +caratteri siano sfuggiti o meno data://all'URL, ma questo dovrebbe essere piuttosto banale.


5

Bene, se stai usando dojo, ci dà un modo diretto per codificare o decodificare in base64.

Prova questo:-

Per codificare una matrice di byte usando dojox.encoding.base64:

var str = dojox.encoding.base64.encode(myByteArray);

Per decodificare una stringa codificata in base64:

var bytes = dojox.encoding.base64.decode(str);

3

Puoi usare window.btoae window.atob...

const encoded = window.btoa('Alireza Dezfoolian'); // encode a string
const decoded = window.atob(encoded); // decode the string

Probabilmente usare il modo in cui è MDN può fare il tuo lavoro nel modo migliore ... Accettare anche unicode ... usando queste due semplici funzioni:

// ucs-2 string to base64 encoded ascii
function utoa(str) {
    return window.btoa(unescape(encodeURIComponent(str)));
}
// base64 encoded ascii to ucs-2 string
function atou(str) {
    return decodeURIComponent(escape(window.atob(str)));
}
// Usage:
utoa('✓ à la mode'); // 4pyTIMOgIGxhIG1vZGU=
atou('4pyTIMOgIGxhIG1vZGU='); // "✓ à la mode"

utoa('I \u2661 Unicode!'); // SSDimaEgVW5pY29kZSE=
atou('SSDimaEgVW5pY29kZSE='); // "I ♡ Unicode!"

3

Ecco una DEMO LIVE di atob()e btoa()funzioni integrate di JS:

<!DOCTYPE html>
<html>
  <head>
    <style>
      textarea{
        width:30%;
        height:100px;
      }
    </style>
    <script>
      // encode string to base64
      function encode()
      {
        var txt = document.getElementById("txt1").value;
        var result = btoa(txt);
        document.getElementById("txt2").value = result;
      }
      // decode base64 back to original string
      function decode()
      {
        var txt = document.getElementById("txt3").value;
        var result = atob(txt);
        document.getElementById("txt4").value = result;
      }
    </script>
  </head>
  <body>
    <div>
      <textarea id="txt1">Some text to decode
      </textarea>
    </div>
    <div>
      <input type="button" id="btnencode" value="Encode" onClick="encode()"/>
    </div>
    <div>
      <textarea id="txt2">
      </textarea>
    </div>
    <br/>
    <div>
      <textarea id="txt3">U29tZSB0ZXh0IHRvIGRlY29kZQ==
      </textarea>
    </div>
    <div>
      <input type="button" id="btndecode" value="Decode" onClick="decode()"/>
    </div>
    <div>
      <textarea id="txt4">
      </textarea>
    </div>
  </body>
</html>

2

Utilizzare la libreria js-base64 come

btoa () non funziona con gli emoji

var str = "I was funny 😂";
console.log("Original string:", str);

var encodedStr = Base64.encode(str)
console.log("Encoded string:", encodedStr);

var decodedStr = Base64.decode(encodedStr)
console.log("Decoded string:", decodedStr);
<script src="https://cdn.jsdelivr.net/npm/js-base64@2.5.2/base64.min.js"></script>

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.