Esistono metodi in JavaScript che potrebbero essere utilizzati per codificare e decodificare una stringa utilizzando la codifica base64?
Esistono metodi in JavaScript che potrebbero essere utilizzati per codificare e decodificare una stringa utilizzando la codifica base64?
Risposte:
Alcuni browser come Firefox, Chrome, Safari, Opera e IE10 + possono gestire Base64 in modo nativo. Dai un'occhiata a questa domanda StackOverflow . Sta usando btoa()
e atob()
funzioni .
Per JavaScript lato server (nodo), è possibile utilizzare Buffer
s per decodificare.
Se stai cercando una soluzione cross-browser, ci sono librerie esistenti come CryptoJS o codice come:
http://ntt.cc/2008/01/19/base64-encoder-decoder-with-javascript.html
Con quest'ultimo, è necessario testare accuratamente la funzione per la compatibilità tra browser. E l'errore è già stato segnalato .
new Buffer('Hello, world!').toString('base64');
new Buffer('SGVsbG8sIHdvcmxkIQ==', 'base64').toString('ascii');
(fonte)
new Buffer(string)
è obsoleto. Buffer.from(jwt.split('.')[1], 'base64').toString()
Nei browser basati su Gecko / WebKit (Firefox, Chrome e Safari) e Opera, puoi utilizzare btoa () e atob () .
Risposta originale: come si può codificare una stringa in Base64 in JavaScript?
// 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!"
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();
Per codificare una matrice di byte utilizzando dojox.encoding.base64:
var str = dojox.encoding.base64.encode(myByteArray);
Per decodificare una stringa codificata in base64:
var bytes = dojox.encoding.base64.decode(str)
<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=');
}]);
Se vuoi saperne di più su come codifica base64 in generale e in JavaScript in particolare, consiglierei questo articolo: Informatica in JavaScript: codifica Base64
c2
e probabilmente c1
e c3
quindi non funzionerà "use strict"
come definito sopra.
Ecco una versione rafforzata del post di Sniper. Presume una stringa base64 ben formata senza ritorni a capo. Questa versione elimina un paio di loop, aggiunge la &0xff
correzione da Yaroslav, elimina i null finali, oltre a un po 'di codice 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;
};
decodeBase64=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};
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++;
Funzione di decodifica JavaScript Base64 breve e veloce senza fail-safe:
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;
}
function b64_to_utf8( str ) {
return decodeURIComponent(escape(window.atob( str )));
}
Il progetto php.js ha implementazioni JavaScript di molte delle funzioni di PHP. base64_encode
e base64_decode
sono inclusi.
Qualcuno ha detto il codice golf? =)
Quello che segue è il mio tentativo di migliorare il mio handicap, al passo con i tempi. Fornito per la vostra convenienza.
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;
}
Quello che stavo cercando in realtà era un'implementazione asincrona e con mia sorpresa si scopre forEach
che l' $([]).each
implementazione del metodo di JQuery è molto sincrona.
Se anche tu avevi in mente idee così folli, un ritardo 0 window.setTimeout
eseguirà la decodifica base64 in modo asincrono ed eseguirà la funzione di richiamata con il risultato al termine.
function decode_base64_async(s, cb) {
setTimeout(function () { cb(decode_base64(s)); }, 0);
}
@Toothbrush ha suggerito "indicizza una stringa come un array", e sbarazzati di split
. Questa routine sembra davvero strana e non è sicura di quanto sia compatibile, ma colpisce un altro uccellino quindi lasciamolo.
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;
}
Durante il tentativo di trovare ulteriori informazioni su stringa JavaScript come serie mi sono imbattuto in questa pro punta utilizzando /./g
un'espressione regolare per passo attraverso una stringa. Ciò riduce ulteriormente le dimensioni del codice sostituendo la stringa in posizione ed eliminando la necessità di mantenere una variabile di ritorno.
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);
});
}
Se invece stavi cercando qualcosa di un po 'più tradizionale, forse quanto segue è più di tuo gusto.
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;
}
Non ho avuto il problema nullo finale quindi questo è stato rimosso per rimanere alla pari, ma dovrebbe essere facilmente risolto con un trim()
o un trimRight()
se preferisci, se questo ti crea un problema.
vale a dire.
return r.trimRight();
Il risultato è una stringa di byte ASCII, se è necessario unicode il più semplice è escape
la stringa di byte che può quindi essere decodificata decodeURIComponent
per produrre la stringa di Unicode.
function decode_base64_usc(s) {
return decodeURIComponent(escape(decode_base64(s)));
}
Poiché escape
è deprecato, potremmo modificare la nostra funzione per supportare direttamente Unicode senza la necessità escape
o String.fromCharCode
possiamo produrre una %
stringa con escape pronta per la decodifica URI.
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!
split
la stringa, poiché è possibile indicizzare una stringa JavaScript come un array. s.split('').forEach(function ...
può essere sostituito da [].forEach.call(s, function ...
. Dovrebbe essere molto più veloce, a causa del fatto che non è necessario dividere la stringa.
Ho provato le routine Javascript su phpjs.org e hanno funzionato bene.
Ho provato per la prima volta le routine suggerite nella risposta scelta da Ranhiru Cooray - http://ntt.cc/2008/01/19/base64-encoder-decoder-with-javascript.html
Ho scoperto che non funzionavano in tutte le circostanze. Ho scritto un caso di prova in cui queste routine falliscono e le ho pubblicate su GitHub su:
https://github.com/scottcarter/base64_javascript_test_data.git
Ho anche pubblicato un commento sul post del blog su ntt.cc per avvisare l'autore (in attesa di moderazione: l'articolo è vecchio, quindi non sono sicuro se il commento verrà pubblicato).
In Node.js possiamo farlo in modo semplice
var base64 = 'SGVsbG8gV29ybGQ='
var base64_decode = new Buffer(base64, 'base64').toString('ascii');
console.log(base64_decode); // "Hello World"
Per i framework JavaScripts in cui non esiste un atob
metodo e nel caso in cui non si desideri importare librerie esterne, questa è una funzione breve che lo fa.
Otterrebbe una stringa che contiene un valore codificato Base64 e restituirà una matrice decodificata di byte (in cui la matrice di byte è rappresentata come matrice di numeri in cui ogni numero è un numero intero compreso tra 0 e 255 inclusi).
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};
}
Risorse utilizzate: RFC-4648 Sezione 4