Base64-Codierung und -Decodierung in clientseitigem Javascript

Antworten:

212

Einige Browser wie Firefox, Chrome, Safari, Opera und IE10 + können Base64 nativ verarbeiten. Schauen Sie sich diese Stackoverflow-Frage an . Es benutzt btoa()und atob()funktioniert .

Für serverseitiges JavaScript (Node) können Sie Buffers zum Dekodieren verwenden.

Wenn Sie sich für eine browserübergreifende Lösung entscheiden, gibt es vorhandene Bibliotheken wie CryptoJS oder Code wie:

http://ntt.cc/2008/01/19/base64-encoder-decoder-with-javascript.html

Bei letzterem müssen Sie die Funktion gründlich auf Cross-Browser-Kompatibilität testen. Und Fehler wurde bereits gemeldet .

Ranhiru Jude Cooray
quelle
1
Ich habe diese Methode verwendet, um eine SVG in base64 mit dem Datums-URI-Schema zu codieren. Überraschung: Diese Funktion verschlüsselt jedes Zeichen, sodass ich dieses fehlerhafte XML am Ziel erhalte:% 3C% 3Fxml% 20version% 3D% 271,0% 27% 20% 3F% 3E% 3Csvg% 20xmlns% 3D% 27http% ...
Dereckson
21
Node.js kann Base64 nativ new Buffer('Hello, world!').toString('base64'); new Buffer('SGVsbG8sIHdvcmxkIQ==', 'base64').toString('ascii');
ausführen
Und wenn ich es URL-sicher machen wollte?
Anddero
1
Verwenden Sie in Knoten 5+ Buffer.from, da dies new Buffer(string)veraltet ist. Buffer.from(jwt.split('.')[1], 'base64').toString()
Ray Foss
63

In Gecko / WebKit-basierten Browsern (Firefox, Chrome und Safari) und Opera können Sie btoa () und atob () verwenden .

Ursprüngliche Antwort: Wie können Sie eine Zeichenfolge in JavaScript in Base64 codieren?

nyuszika7h
quelle
Dies ist ein Lebensretter. Ich habe ein paar verschiedene Implementierungen verwendet, um sehr große Base64-codierte Zeichenfolgen zu dekodieren, und das Ergebnis war immer falsch. atob () funktioniert super!
B2238488
15
Kleiner Trottel: Opera basiert nicht auf Gecko oder Webkit, sondern verwendet eine eigene Rendering-Engine namens Presto.
Peter Olson
Wow, danke dafür. Wusste nicht, dass es in diesen Browsern einen nativen base64-Encoder gibt!
Rob Porter
5
@ PeterOlson Nicht mehr :)
Mustafa
1
Mir ist klar, dass dies ein alter Beitrag ist, aber in Bezug auf @ b2238488 können Sie die base64-Zeichenfolge so aufteilen, dass die Länge jedes Tokens ein Vielfaches von 4 ist, und sie separat dekodieren. Das Ergebnis entspricht dem gleichzeitigen Dekodieren der gesamten Zeichenfolge.
Nyuszika7h
56

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

Neu geschriebene und modularisierte UTF-8- und Base64-Javascript-Codierungs- und Decodierungsbibliotheken / -module für AMD, CommonJS, Nodejs und Browser. Browserübergreifend kompatibel.


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

Aber wie?

Wenn Sie mehr darüber erfahren möchten, wie base64 im Allgemeinen und in JavaScript im Besonderen codiert wird, würde ich diesen Artikel empfehlen: Informatik in JavaScript: Base64-Codierung

Davidcondrey
quelle
1
Zur Info: Die Cross-Browser - Version hat einige bösen Lecks mit c2und wahrscheinlich c1und c3so wird es nicht funktionieren mit , "use strict"wie oben definiert.
Campbeln
41

Hier ist eine verschärfte Version von Snipers Post. Es wird eine gut geformte Base64-Zeichenfolge ohne Wagenrücklauf vorausgesetzt. Diese Version eliminiert ein paar Loops, fügt den &0xffFix von Yaroslav hinzu, eliminiert nachgestellte Nullen und ein bisschen Code Golf.

decodeBase64 = function(s) {
    var e={},i,b=0,c,x,l=0,a,r='',w=String.fromCharCode,L=s.length;
    var A="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
    for(i=0;i<64;i++){e[A.charAt(i)]=i;}
    for(x=0;x<L;x++){
        c=e[s.charAt(x)];b=(b<<6)+c;l+=6;
        while(l>=8){((a=(b>>>(l-=8))&0xff)||(x<(L-2)))&&(r+=w(a));}
    }
    return r;
};
broc.seib
quelle
5
Noch weniger Bytes; DdecodeBase64=function(f){var g={},b=65,d=0,a,c=0,h,e="",k=String.fromCharCode,l=f.length;for(a="";91>b;)a+=k(b++);a+=a.toLowerCase()+"0123456789+/";for(b=0;64>b;b++)g[a.charAt(b)]=b;for(a=0;a<l;a++)for(b=g[f.charAt(a)],d=(d<<6)+b,c+=6;8<=c;)((h=d>>>(c-=8)&255)||a<l-2)&&(e+=k(h));return e};
Der Hochstapler
Ja, funktioniert aber nur mit ASCII. Cyr-Charaktere werden zum Beispiel verstümmelt.
Martin Kovachev
@MartinKovachev Können Sie einen neuen Kommentar mit Beispieltext mit Cyr-Zeichen und der entsprechenden Base64-Codierung veröffentlichen? Vielleicht können wir den Code korrigieren, um ihn anzupassen.
broc.seib
Hier: so etwas: тестова фраза
Martin Kovachev
2
@OliverSalzburg Noch weniger Code-Tabelle generieren :):var g={},k=String.fromCharCode,i;for(i=0;i<64;)g[k(i>61?(i&1)*4|43:i+[65,71,-4][i/26&3])]=i++;
Mike
34

Kurze und schnelle Base64 JavaScript Decode Funktion ohne Ausfallsicherheit:

function decode_base64 (s)
{
    var e = {}, i, k, v = [], r = '', w = String.fromCharCode;
    var n = [[65, 91], [97, 123], [48, 58], [43, 44], [47, 48]];

    for (z in n)
    {
        for (i = n[z][0]; i < n[z][1]; i++)
        {
            v.push(w(i));
        }
    }
    for (i = 0; i < 64; i++)
    {
        e[v[i]] = i;
    }

    for (i = 0; i < s.length; i+=72)
    {
        var b = 0, c, x, l = 0, o = s.substring(i, i+72);
        for (x = 0; x < o.length; x++)
        {
            c = e[o.charAt(x)];
            b = (b << 6) + c;
            l += 6;
            while (l >= 8)
            {
                r += w((b >>> (l -= 8)) % 256);
            }
         }
    }
    return r;
}
Scharfschütze
quelle
6
Opera 11.62 scheint ein Problem mit dem Teil '% 256' zu haben. Wenn Sie es durch '& 0xff' ersetzen, funktioniert es.
Jaroslaw Stavnichiy
Der JavaScript-Code für den virtuellen Tyk-Endpunkt scheint ein Problem mit dem Teil '\ x00' zu haben. Wenn Sie es durch r = r.replace (/ \ x00 / g, '')
ersetzen,
11

Das php.js- Projekt enthält JavaScript-Implementierungen vieler PHP-Funktionen. base64_encodeund base64_decodesind enthalten.

ceejayoz
quelle
php.js ist die Inkarnation allen Übels und gehört zu seiner eigenen Schicht in der Hölle. Vermeiden Sie es wie die Pest. (Weitere Informationen: softwareengineering.stackexchange.com/questions/126671/… )
Coreus
Ich sehe nicht viel Unterstützung für diese pauschale Behauptung in diesem Link, @Coreus. Mit Bedacht oder als Ausgangspunkt verwendet, ist dies eine durchaus akzeptable Methode, um die entsprechende Logik in JS für etwas herauszufinden, das Sie möglicherweise bereits in PHP kennen.
Ceejayoz
8

Hat jemand Code Golf gesagt? =)

Das Folgende ist mein Versuch, mein Handicap zu verbessern und gleichzeitig mit der Zeit Schritt zu halten. Wird für Ihre Bequemlichkeit geliefert.

function decode_base64(s) {
  var b=l=0, r='',
  m='ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/';
  s.split('').forEach(function (v) {
    b=(b<<6)+m.indexOf(v); l+=6;
    if (l>=8) r+=String.fromCharCode((b>>>(l-=8))&0xff);
  });
  return r;
}

Was ich eigentlich wollte, war eine asynchrone Implementierung, und zu meiner Überraschung stellt sich heraus forEach, dass die $([]).eachImplementierung der JQuery- Methode sehr synchron ist.

Wenn Sie auch solche verrückten Vorstellungen hatten, führt eine 0-Verzögerung window.setTimeoutdie base64-Dekodierung asynchron aus und führt die Rückruffunktion mit dem Ergebnis aus, wenn Sie fertig sind.

function decode_base64_async(s, cb) {
  setTimeout(function () { cb(decode_base64(s)); }, 0);
}

@Toothbrush schlug vor, "einen String wie ein Array zu indizieren" und das zu entfernen split. Diese Routine scheint wirklich seltsam und nicht sicher zu sein, wie kompatibel sie sein wird, aber sie trifft einen anderen Birdie, also lasst es uns haben.

function decode_base64(s) {
  var b=l=0, r='',
  m='ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/';
  [].forEach.call(s, function (v) {
    b=(b<<6)+m.indexOf(v); l+=6;
    if (l>=8) r+=String.fromCharCode((b>>>(l-=8))&0xff);
  });
  return r;
}

Beim Versuch, weitere Informationen zu JavaScript-Zeichenfolgen als Array zu finden, bin ich auf diesen Pro-Tipp gestoßen, bei dem ein /./gregulärer Ausdruck verwendet wurde, um eine Zeichenfolge zu durchlaufen. Dies reduziert die Codegröße noch mehr, indem die Zeichenfolge ersetzt wird und keine Rückgabevariable mehr erforderlich ist.

function decode_base64(s) {
  var b=l=0,
  m='ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/';
  return s.replace(/./g, function (v) {
    b=(b<<6)+m.indexOf(v); l+=6;
    return l<8?'':String.fromCharCode((b>>>(l-=8))&0xff);
  });
}

Wenn Sie jedoch nach etwas Traditionellerem suchen, ist das Folgende vielleicht mehr nach Ihrem Geschmack.

function decode_base64(s) {
  var b=l=0, r='', s=s.split(''), i,
  m='ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/';
  for (i in s) {
    b=(b<<6)+m.indexOf(s[i]); l+=6;
    if (l>=8) r+=String.fromCharCode((b>>>(l-=8))&0xff);
  }
  return r;
}

Ich hatte kein nachfolgendes Null-Problem, daher wurde dieses entfernt, um unter dem Nennwert zu bleiben, aber es sollte leicht mit einem trim()oder einem gelöst werden können, trimRight()wenn Sie dies bevorzugen, sollte dies ein Problem für Sie darstellen.

dh.

return r.trimRight();

Hinweis:

Das Ergebnis ist eine ASCII-Byte-Zeichenfolge. Wenn Sie einen Unicode benötigen, ist escapedie Byte-Zeichenfolge am einfachsten, mit der dann decodeURIComponentdie Unicode-Zeichenfolge dekodiert werden kann .

function decode_base64_usc(s) {      
  return decodeURIComponent(escape(decode_base64(s)));
}

Da escapedies veraltet ist, können wir unsere Funktion ändern, um Unicode direkt zu unterstützen, ohne dass dies erforderlich ist, escapeoder String.fromCharCodewir können eine %maskierte Zeichenfolge erstellen, die für die URI-Decodierung bereit ist.

function decode_base64(s) {
  var b=l=0,
  m='ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/';
  return decodeURIComponent(s.replace(/./g, function (v) {
    b=(b<<6)+m.indexOf(v); l+=6;
    return l<8?'':'%'+(0x100+((b>>>(l-=8))&0xff)).toString(16).slice(-2);
  }));
}

nJoy!

Nickl-
quelle
3
Sie müssen splitdie Zeichenfolge nicht verwenden, da Sie eine JavaScript-Zeichenfolge wie ein Array indizieren können. s.split('').forEach(function ...kann ersetzt werden durch [].forEach.call(s, function .... Es sollte viel schneller sein, da es den String nicht teilen muss.
Zahnbürste
Das "traditionellere" war für mich völlig kaputt - es entstand ein verstümmeltes Durcheinander mit Spuren von Originaltext, die überall verteilt waren. Auf Chrome.
Steve Bennett
@Steve Bennett Ich habe alle Varianten in Chrom getestet ... es funktioniert. Können Sie eine Beispiel-Base64-Zeichenfolge angeben, die fehlschlägt?
Nickl
Drei Jahre später? Ha. Ich erinnere mich nicht einmal, wofür ich das brauchte.
Steve Bennett
6

Ich habe die Javascript-Routinen auf phpjs.org ausprobiert und sie haben gut funktioniert.

Ich habe zuerst die Routinen ausprobiert, die in der von Ranhiru Cooray gewählten Antwort vorgeschlagen wurden - http://ntt.cc/2008/01/19/base64-encoder-decoder-with-javascript.html

Ich stellte fest, dass sie nicht unter allen Umständen funktionierten. Ich habe einen Testfall geschrieben, in dem diese Routinen fehlschlagen, und sie auf GitHub gepostet unter:

https://github.com/scottcarter/base64_javascript_test_data.git

Ich habe auch einen Kommentar zum Blog-Beitrag auf ntt.cc gepostet, um den Autor zu benachrichtigen (wartet auf Moderation - der Artikel ist alt, daher nicht sicher, ob ein Kommentar veröffentlicht wird).

Scott Carter
quelle
1

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 mithilfe von Best Practices und Mustern implementiert sind.

Dan Dascalescu
quelle
1

In Node.js können wir das auf einfache Weise tun

var base64 = 'SGVsbG8gV29ybGQ='
var base64_decode = new Buffer(base64, 'base64').toString('ascii');

console.log(base64_decode); // "Hello World"
KARTHIKEYAN.A
quelle
0

Für JavaScripts-Frameworks, bei denen es keine atobMethode gibt und Sie keine externen Bibliotheken importieren möchten, ist dies eine kurze Funktion, die dies ausführt.

Es würde eine Zeichenfolge erhalten, die einen Base64-codierten Wert enthält und ein decodiertes Array von Bytes zurückgibt (wobei das Array von Bytes als Array von Zahlen dargestellt wird, wobei jede Zahl eine Ganzzahl zwischen 0 und einschließlich 255 ist).

function fromBase64String(str) {
    var alpha = 
    "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
    var value = [];
    var index = 0;
    var destIndex  = 0;
    var padding = false;
    while (true) {

        var first  = getNextChr(str, index, padding, alpha);
        var second = getNextChr(str, first .nextIndex, first .padding, alpha);
        var third  = getNextChr(str, second.nextIndex, second.padding, alpha);
        var fourth = getNextChr(str, third .nextIndex, third .padding, alpha);

        index = fourth.nextIndex;
        padding = fourth.padding;

        // ffffffss sssstttt ttffffff
        var base64_first  = first.code  == null ? 0 : first.code;
        var base64_second = second.code == null ? 0 : second.code;
        var base64_third  = third.code  == null ? 0 : third.code;
        var base64_fourth = fourth.code == null ? 0 : fourth.code;

        var a = (( base64_first << 2) & 0xFC ) | ((base64_second>>4) & 0x03);
        var b = (( base64_second<< 4) & 0xF0 ) | ((base64_third >>2) & 0x0F);
        var c = (( base64_third << 6) & 0xC0 ) | ((base64_fourth>>0) & 0x3F);

        value [destIndex++] = a;
        if (!third.padding) {
            value [destIndex++] = b;
        } else {
            break;
        }
        if (!fourth.padding) {
            value [destIndex++] = c;
        } else {
            break;
        }
        if (index >= str.length) {
            break;
        }
    }
    return value;
}

function getNextChr(str, index, equalSignReceived, alpha) {
    var chr = null;
    var code = 0;
    var padding = equalSignReceived;
    while (index < str.length) {
        chr = str.charAt(index);
        if (chr == " " || chr == "\r" || chr == "\n" || chr == "\t") {
            index++;
            continue;
        }
        if (chr == "=") {
            padding = true;
        } else {
            if (equalSignReceived) {
                throw new Error("Invalid Base64 Endcoding character \"" 
                    + chr + "\" with code " + str.charCodeAt(index) 
                    + " on position " + index 
                    + " received afer an equal sign (=) padding "
                    + "character has already been received. "
                    + "The equal sign padding character is the only "
                    + "possible padding character at the end.");
            }
            code = alpha.indexOf(chr);
            if (code == -1) {
                throw new Error("Invalid Base64 Encoding character \"" 
                    + chr + "\" with code " + str.charCodeAt(index) 
                    + " on position " + index + ".");
            }
        }
        break;
    }
    return { character: chr, code: code, padding: padding, nextIndex: ++index};
}

Verwendete Ressourcen: RFC-4648 Abschnitt 4

Yordan Nedelchev
quelle