Wie können Sie eine Zeichenfolge in JavaScript in Base64 codieren?


810

Ich habe ein PHP-Skript, das ein PNG-Bild in eine Base64-Zeichenfolge codieren kann.

Ich möchte dasselbe mit JavaScript tun. Ich weiß, wie man Dateien öffnet, bin mir aber nicht sicher, wie ich die Codierung durchführen soll. Ich bin es nicht gewohnt, mit Binärdaten zu arbeiten.


2
Hier ist der beste Weg, um base64_encode und base64_decode mit Javascript zu erstellen. Siehe unten stehende Links. phpjs.org/functions/base64_encode:358 phpjs.org/functions/base64_decode:357
gautamlakum

Hier ist ein weiteres JQuery Plugin für Base64 Codierung / Decodierung
Zahid9i

Überprüfen Sie microjs: microjs.com/#base64
Vinod Srivastav

Antworten:


866

Sie können die Base64-Codierung verwenden btoa()und atob()in diese konvertieren.

In den Kommentaren scheint es einige Verwirrung darüber zu geben, was diese Funktionen akzeptieren / zurückgeben, also ...

  • btoa()Akzeptiert eine „Zeichenfolge“, in der jedes Zeichen ein 8-Bit-Byte darstellt. Wenn Sie eine Zeichenfolge übergeben, die Zeichen enthält, die nicht in 8 Bit dargestellt werden können, wird sie wahrscheinlich unterbrochen . Dies ist kein Problem, wenn Sie die Zeichenfolge tatsächlich als Byte-Array behandeln. Wenn Sie jedoch versuchen, etwas anderes zu tun, müssen Sie sie zuerst codieren.

  • atob()Gibt eine „Zeichenfolge“ zurück, in der jedes Zeichen ein 8-Bit-Byte darstellt. Das heißt, sein Wert liegt zwischen 0und 0xff. Dies bedeutet nicht, dass es sich um ASCII handelt. Wenn Sie diese Funktion überhaupt verwenden, erwarten Sie vermutlich, dass Sie mit Binärdaten und nicht mit Text arbeiten.

Siehe auch:


47
Beachten Sie, dass dies auch für Webkit-Browser wie Safari funktioniert.
Daniel Von Fange

5
Auf dem iPhone3G mit iOS 4.1 funktioniert dies jedoch nicht. Es funktioniert auf dem Simulator iPhone Simulator, wenn es auf iPhone4 oder iPhone eingestellt ist.
Grant M

29
Bitte beachten Sie die besondere Überlegung für Unicode-Zeichenfolgen: developer.mozilla.org/En/DOM/Window.btoa#Unicode_Strings btoa und atob funktionieren nur für ASCII-basierte Zeichenfolgen ordnungsgemäß. Als Amerikaner werden Sie wahrscheinlich keinen Unterschied bemerken ... aber wenn Sie zum ersten Mal ein Zeichen mit Akzent verwenden, wird Ihr Code beschädigt.
Dan Esparza

70
Sie sollten verwenden, btoa(unescape(encodeURIComponent(str))))wenn str UFT8 ist
SET

4
Siehe meine Bearbeitung, @Triynko. Diese sind nicht zur Verarbeitung von Text , Punkt gedacht .
Shog9

289

Von hier aus :

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

}

Auch die Suche nach "Javascript Base64-Codierung" bietet viele andere Optionen, die oben genannte war die erste.


3
Dies ist auch nützlich, wenn die Base64-Codierung nicht dem Standard entspricht. In meinem Fall wurde das Zeichen "/" nicht verwendet und das Zeichen "?" Stattdessen wurde das Zeichen verwendet, was bedeutet, dass selbst in Chrome atob () die eingehenden base64-Zeichenfolgen nicht dekodieren würde.
Chris Moschini

21
Seien Sie vorsichtig mit diesem Code - er versucht, Ihre Zeichenfolge als UTF-8-codierte Zeichenfolge zu interpretieren. Wir hatten einen Fall, in dem wir eine binäre Zeichenfolge hatten (dh jedes Zeichen in der Zeichenfolge sollte als Byte interpretiert werden), und dieser Code hat die Daten beschädigt. Lies die Quelle, Luke.
Daniel Yankowsky

11
Alles, was benötigt wird, um es für die meisten binären Codierungen / Decodierungen sicher zu machen, um die fragwürdige string = string.replace(/\r\n/g,"\n");Anweisung in der utf8-Codierungsmethode zu entfernen .
Marius

7
@Marius: Ich frage mich, warum sie sie überhaupt aufnehmen würden string = string.replace(/\r\n/g,"\n");, lol. Es ist wie "Oh, lassen Sie uns diese Zeichenfolge codieren, aber warum normalisieren wir nicht einfach alle Zeilenumbrüche ohne guten Grund zufällig". Das sollte unter allen Umständen unbedingt aus der Klasse entfernt werden.
Triynko

2
Ich bin kein Javascript-Guru, aber dieser Code scheint einen Fehler zu enthalten: Wenn chr2 NaN ist, wird sein Wert immer noch in der Anweisung verwendet enc2 = ((chr1 & 3) << 4) | (chr2 >> 4);. In meinem Browser funktioniert das in Ordnung, NaN>>4gleich 0, aber ich weiß nicht, ob alle Browser dies tun ( NaN/16entspricht auch NaN).
Januar

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

Browserübergreifend

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


mit Node.js.

So codieren Sie normalen Text 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');

Und so dekodieren Sie Base64-codierte Zeichenfolgen:

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

mit Dojo.js

So codieren Sie ein Array von Bytes mit dojox.encoding.base64:

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

So dekodieren Sie eine Base64-codierte Zeichenfolge:

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

Laube eckig-base64 einbauen

<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
Diese Antwort basiert auf dem Originalcode und enthält KEINE Aktualisierungen dieses Codes, die in anderen Antworten hier veröffentlicht wurden.
Eugene Ryabtsev

Die vorgeschlagene NodeJS-Lösung ist veraltet.
Vladimir Nul

94

Sunnys Code ist großartig, außer dass er in IE7 aufgrund von Verweisen auf "this" kaputt geht. Behoben durch Ersetzen solcher Referenzen durch "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
Oh mein schlechtes, ich habe die Eingabe von der Browser-URL genommen; wo | wird in% 7C umgewandelt; daher ist auch die Kodierung falsch.
Kanagavelu Sugumar

Ich weiß, dass dies wirklich alt ist, aber ich habe gesehen, dass diese Funktion an mehr als einer Stelle verwendet wurde. Die Schlüsselzeichenfolge besteht tatsächlich aus 65 Zeichen, nicht aus 64. Die Zeichenfolge ist keine Standardspezifikation. Ich bin mir nicht sicher, ob sie wichtig ist, habe mich aber nur gefragt wenn ja?
Jonathan Wagner

"benutze streng"; ist das, was das 'dies' und andere Typelemente wie 'mit' bricht und von dem, was ich gelesen habe, bekommt 'eval' einen Schlag. Alle fehlgeleiteten Vorstellungen über Missbrauch. Persönlich verstehe ich nicht, warum JavaScript den Weg gehen muss, es war nie dazu gedacht, ein Programm zu sein, das eng gebunden und komplexer ist als es bereits ist. Wenn Sie gebunden werden möchten, erstellen Sie einen Compiler für Javascript.
Mark Giblin

Ich versuche, diese Funktion zu verwenden, und erhalte die folgende Fehlermeldung: Verursacht durch: org.mozilla.javascript.EcmaError: TypeError: Im Objekt teste teste teste kann keine Funktion gefunden werden. Ich versuche, .txt mit "teste teste teste" zu codieren. Weiß jemand warum dieser Fehler?
PRVS

@ JonathanWagner - Für die normale Codierung werden 64 Zeichen verwendet. Das 65. Zeichen wird zum Auffüllen verwendet. Die Eingabezeichenfolge enthält keine durch 3 teilbare Anzahl von Zeichen.
Kickstart

90

Sie können btoa(von base-64) und atob(von base-64) verwenden.

Probieren Sie für IE 9 und niedriger das Plugin jquery-base64 aus :

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

133
Warum muss alles ein jQuery-Plugin sein: c Dies ist nur die Kernfunktionalität von JavaScript. Dies hat nichts mit dem DOM oder jQuery zu tun
EaterOfCode

38
Dies ist keine Kernfunktionalität, oder es würde nicht so viele verschiedene Antworten mit hohen Stimmen geben (einschließlich Do-it-yourself-Code). Imho ist dies also ein guter Anwendungsfall für jQuery (ein Liner, der voraussichtlich sogar in Android WebView funktioniert) - noch mehr, wenn es sich bereits um eine Abhängigkeit handelt.
Risadinha

1
Ich mag es, solche Codefragmente in jQuery zu installieren, hauptsächlich weil sie in einem kontrollierten Namespace existieren. Wenn Sie AMD oder CommonJS oder ein ähnliches Entwurfsmuster nicht verwenden, kann Ihr globaler Namespace mit einer Reihe von Zufallsfunktionen leicht durcheinander geraten.
sffc

9
@Risadinha - außer dass seine Funktionalität überhaupt nicht von jQuery abhängt oder es erweitert ... buchstäblich die einzigen Verweise auf jQuery in seinem Code sind das Anhängen an das jQuery-Objekt ... also was bringt es, es an jQuery anzuhängen und es daher zu erfordern jQuery zu verwenden? Machen Sie es einfach zu einem eigenen 1-Liner base64.encode(...)und base64.decode(...)... das Anhängen an jQuery, wenn es keine jQuery-spezifische Funktionalität hat, macht absolut keinen Sinn ...
Jimbo Jonny

1
jQuery wurde nicht angefordert. Keine gültige Antwort auf eine einfache alte JS-Frage.
MetaColin

34

In den Kommentaren (von SET und Stefan Steiger) unter der akzeptierten Antwort finden Sie eine kurze Zusammenfassung, wie Sie einen String zu / von base64 codieren / decodieren, ohne eine Bibliothek zu benötigen.

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

Demo

(Verwendet die jQuery-Bibliothek, jedoch nicht zum Codieren / Decodieren)


Zur Bestätigung unterstützt dies UTF-8-Zeichen?
Crashalot

1
@Crashalot Mir ist klar, dass dies zwei Jahre zu spät ist, aber ja, das tut es. Während ich dies tippe, stelle ich auch gerade fest, dass Sie eine Bearbeitung bereitgestellt haben, die möglicherweise dazu geführt hat, dass UTF8 funktioniert.
Tycrek

Für alle, die hier nach einer guten Lösung für Node.js suchen, kann ich bestätigen, dass dies funktioniert. Für die Dekodierung in Node habe ich verwendet:Buffer.from(b64data, 'base64').toString();
tycrek

26

Es gibt ein paar Fehler in beiden Implementierungen von _utf8_decode. c1und c2werden aufgrund der fehlerhaften Verwendung der varAnweisung als globale Variablen zugewiesen und überhaupt c3nicht initialisiert oder deklariert.

Es funktioniert, aber diese Variablen überschreiben alle vorhandenen Variablen mit demselben Namen außerhalb dieser Funktion.

Hier ist eine Version, die dies nicht tut:

// 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 Ich hatte nicht genug Repräsentanten, um Antworten zu bearbeiten, als ich diese Antwort schrieb ... im Jahr 2011.
Robbles

2
IE7? Ich denke, wir sollten aufhören, Zeit zu verschwenden, um Code dafür zu schreiben. Die Leute werden nicht aufhören, diese alte Technologie zu verwenden, es sei denn, wir Entwickler haben sie dazu gezwungen!
Rami Dabain

@ RonanDejhero funktioniert es nicht in IE7? Ich erinnere mich nicht, ob ich in diesem bestimmten Browser getestet habe.
Robbles

1
Was ich damit gemeint habe, wenn es in IE7 nicht funktioniert, sollte es niemanden interessieren!. Ich habe es nicht getestet und werde es auch nicht testen :)
Rami Dabain

16

Ich habe Sunnys Antwort beantwortet, aber ich wollte ein paar Änderungen zurückbringen, die ich für mein eigenes Projekt vorgenommen habe, falls jemand es nützlich finden sollte. Grundsätzlich habe ich den ursprünglichen Code nur ein wenig aufgeräumt, damit sich JSLint nicht so sehr beschwert, und ich habe die Methoden, die in den Kommentaren als privat markiert sind, tatsächlich privat gemacht. Ich habe auch zwei Methoden hinzugefügt, die ich in meinem eigenen Projekt brauchte, nämlich decodeToHexund encodeFromHex.

Der Code:

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

Ich dachte anfangs, dass das Abrollen der Ausgabekettung in separate Anweisungen optimaler wäre, aber nachdem ich eine Sekunde lang darüber nachgedacht habe, sollte dies ineffizienter sein, da Javascript-Zeichenfolgen unveränderlich sind und beim Arbeiten 4 Kopien potenziell großer Datenblobs verursachen würden mit großen binären Datendateien. Es ist sicherer, zuerst die 4 Zeichen miteinander zu verketten und dann eine neue Zeichenfolge zu erstellen. Ich wünschte, ich wüsste mit Sicherheit eine bessere Methode zum Erstellen von Strings, die auf allen Plattformen effizient sein würde. (sogar IE6)
Marius

Ich habe die Leistung bei der Bereinigung des ursprünglich veröffentlichten Codes nicht berücksichtigt. Ich habe es nur lesbarer gemacht und Methoden, die in den Kommentaren im Original als privat markiert sind, mithilfe des aufschlussreichen Modulmusters tatsächlich privat gemacht. Ich bin sicher, dass es auch in Bezug auf die Leistung optimiert werden kann. Ich bin mir nicht ganz sicher, wann die Speicherbereinigung hier beginnen würde, und das Hashing großer Dateien über Javascript ist nicht sehr verbreitet (oder wahrscheinlich auf keinen Fall die optimale Lösung).
Joe Dyndale

Komisch, wie dieser Code hier lebt. Es gibt bereits 3 verschiedene Versionen davon auf dieser Seite.
gregn3

15

Für neuere Browser, die Uint8Array als Zeichenfolge codieren und die Zeichenfolge als Zeichenfolge für Uint8Array dekodieren.

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

Für Node.js können Sie Folgendes verwenden, um Zeichenfolge, Puffer oder Uint8Array in Zeichenfolge zu codieren und von Zeichenfolge, Puffer oder Uint8Array in Puffer zu dekodieren.

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

13

Um eine Base64-codierte String-URL benutzerfreundlich zu gestalten, können Sie in JavaScript Folgendes tun:

// 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, '/');

Siehe auch diese Geige: http://jsfiddle.net/magikMaker/7bjaT/


9
Ich würde demütig vorschlagen, dass die Verwendung von encodeURIComponentdurchaus zu einem überlegenen Ergebnis mit weniger Aufwand seitens des Entwicklers führen kann.
Pablo Fernandez

11
encodeURIComponent ändert die Länge der Base64-codierten Zeichenfolgen, und das Ersetzen von '-' und '_' durch '+' und '/' ist Standard, wenn base64 in URLs verwendet wird (z. B. docs.python.org/library/base64.html#base64) .urlsafe_b64encode ). Keine Notwendigkeit, sich aufzuregen.
Natevw


12

Ich habe diese Kodierungs- und Dekodierungsmethoden mit Ausnahme der hexadezimalen Methode von Hand in ein modulares Format umgeschrieben, um sie plattformübergreifend / browserkompatibel und auch mit echtem privatem Umfang und Verwendungszwecken zu verwenden, btoaund atobwenn sie aufgrund der Geschwindigkeit existieren, anstatt sie zu nutzen seine eigene Kodierung:

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

Verwendungszweck:

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

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

12

Diese Frage und ihre Antworten haben mich in die richtige Richtung gelenkt.
Besonders mit Unicode Atob und Btoa kann nicht "Vanille" verwendet werden und heutzutage ist ALLES Unicode ..

Direkt von Mozilla, zwei nette Funktionen für diesen Zweck (getestet mit Unicode- und HTML-Tags im Inneren)

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"

Diese Funktionen werden im Vergleich zur rohen Base64-Decodierung mit einer benutzerdefinierten Javascript-Funktion blitzschnell ausgeführt, da btoa und atob außerhalb des Interpreters ausgeführt werden.

Wenn Sie alten Internet Explorer und alte Mobiltelefone (wie iPhone 3?) Ignorieren können, sollte dies eine gute Lösung sein.


10

Wenn Sie ein HTML-Bildobjekt codieren müssen, können Sie einfache Funktionen wie die folgenden schreiben:

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
}  

So erhalten Sie base64 des Bildes anhand der ID:

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

mehr hier


Ja und var img = neues Bild (); img.src = "../images/myPic.png";
pdschuller

7

Beitrag mit einer minimierten Polyfüllung für window.atob+ window.btoa, die ich derzeit verwende.

(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

Ich würde lieber die bas64-Codierungs- / Decodierungsmethoden von CryptoJS verwenden , der beliebtesten Bibliothek für standardmäßige und sichere kryptografische Algorithmen, die in JavaScript unter Verwendung von Best Practices und Mustern implementiert sind.


6

Hier ist eine AngularJS Factory-Version von @ 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

Ich brauchte die Codierung eines UTF-8-Strings als base64 für ein Projekt von mir. Die meisten Antworten hier scheinen UTF-16-Ersatzpaare bei der Konvertierung in UTF-8 nicht richtig zu behandeln. Aus Gründen der Vervollständigung werde ich meine Lösung veröffentlichen:

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

Beachten Sie, dass der Code nicht gründlich getestet wurde. Ich habe einige Eingaben getestet, darunter Dinge wie strToUTF8Base64('衠衢蠩蠨')und verglichen mit der Ausgabe eines Online-Codierungstools ( https://www.base64encode.org/ ).


5

Für mein Projekt muss ich noch IE7 unterstützen und mit großen Eingaben arbeiten, um zu codieren.

Basierend auf dem von Joe Dyndale vorgeschlagenen Code und dem Kommentar von Marius ist es möglich, die Leistung mit IE7 zu verbessern, indem das Ergebnis mit einem Array anstelle eines Strings erstellt wird.

Hier ist das Beispiel für die Codierung:

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

Wenn Sie eine native Hochleistungslösung wünschen, können Sie einige HTML5-Funktionen verwenden.

Wenn Sie Ihre Daten in a übertragen können Blob, können Sie mit der Funktion FileReader.readAsDataURL () eine data://URL abrufen und die Vorderseite abhacken, um an die base64-Daten zu gelangen.

Möglicherweise müssen Sie jedoch eine weitere Verarbeitung durchführen, um die Daten zu urldecodieren, da ich nicht sicher bin, ob +Zeichen für die data://URL maskiert sind oder nicht , aber dies sollte ziemlich trivial sein.


5

Wenn Sie Dojo verwenden, können wir direkt in base64 codieren oder decodieren.

Versuche dies:-

So codieren Sie ein Array von Bytes mit dojox.encoding.base64:

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

So dekodieren Sie eine Base64-codierte Zeichenfolge:

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

3

Sie können verwenden window.btoaund window.atob...

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

Wahrscheinlich kann die Verwendung der Art und Weise, wie MDN ist, Ihre Arbeit am besten erledigen ... Auch das Akzeptieren von Unicode ... mithilfe dieser beiden einfachen Funktionen:

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

Hier ist eine LIVE DEMO von atob()und btoa()JS integrierte Funktionen:

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

Verwenden Sie die js-base64-Bibliothek als

btoa () funktioniert nicht mit Emojis

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>

Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.