¿Hay algún método en JavaScript que pueda usarse para codificar y decodificar una cadena usando codificación base64?
¿Hay algún método en JavaScript que pueda usarse para codificar y decodificar una cadena usando codificación base64?
Respuestas:
Algunos navegadores como Firefox, Chrome, Safari, Opera e IE10 + pueden manejar Base64 de forma nativa. Echa un vistazo a esta pregunta de Stackoverflow . Está usando btoa()
y atob()
funciones .
Para JavaScript del lado del servidor (Nodo), puede usar Buffer
s para decodificar.
Si está buscando una solución de navegador cruzado, hay bibliotecas existentes como CryptoJS o código como:
http://ntt.cc/2008/01/19/base64-encoder-decoder-with-javascript.html
Con este último, debe probar a fondo la función para la compatibilidad entre navegadores. Y el error ya ha sido reportado .
new Buffer('Hello, world!').toString('base64');
new Buffer('SGVsbG8sIHdvcmxkIQ==', 'base64').toString('ascii');
(fuente)
new Buffer(string)
está en desuso. Buffer.from(jwt.split('.')[1], 'base64').toString()
En los navegadores basados en Gecko / WebKit (Firefox, Chrome y Safari) y Opera, puede usar btoa () y atob () .
Respuesta original: ¿Cómo puede codificar una cadena a Base64 en 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!"
Así es como codifica el texto normal a base64 en 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');
Y así es como decodifica cadenas codificadas en base64:
var b = new Buffer('SmF2YVNjcmlwdA==', 'base64')
var s = b.toString();
Para codificar una matriz de bytes usando dojox.encoding.base64:
var str = dojox.encoding.base64.encode(myByteArray);
Para decodificar una cadena codificada en 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=');
}]);
Si desea obtener más información sobre cómo se codifica base64 en general, y en JavaScript en particular, le recomendaría este artículo: Informática en JavaScript: codificación Base64
c2
y es probable c1
y c3
lo que no funciona con "use strict"
los definidos anteriormente.
Aquí hay una versión más estricta de la publicación de Sniper. Presume una cadena base64 bien formada sin retornos de carro. Esta versión elimina un par de bucles, agrega la &0xff
solución de Yaroslav, elimina los nulos finales, además de un poco de código de 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++;
Función de decodificación de JavaScript Base64 corta y rápida sin seguridad:
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 )));
}
El proyecto php.js tiene implementaciones de JavaScript de muchas de las funciones de PHP. base64_encode
y base64_decode
están incluidos
¿Alguien dijo código golf? =)
El siguiente es mi intento de mejorar mi discapacidad mientras me pongo al día. Suministrado para su conveniencia.
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;
}
Lo que realmente buscaba era una implementación asincrónica y, para mi sorpresa, resulta forEach
que la $([]).each
implementación del método de JQuery es muy sincrónica.
Si también tenía en mente esas ideas locas, un retraso de 0 window.setTimeout
ejecutará la decodificación base64 de forma asincrónica y ejecutará la función de devolución de llamada con el resultado cuando haya terminado.
function decode_base64_async(s, cb) {
setTimeout(function () { cb(decode_base64(s)); }, 0);
}
@Toothbrush sugirió "indexar una cadena como una matriz" y deshacerse de split
. Esta rutina parece realmente extraña y no estoy seguro de cuán compatible será, pero golpea a otro pajarito, así que vamos a tenerla.
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;
}
Mientras intentaba encontrar más información sobre la cadena de JavaScript como matriz, me topé con este consejo profesional usando una /./g
expresión regular para recorrer una cadena. Esto reduce aún más el tamaño del código al reemplazar la cadena en su lugar y eliminar la necesidad de mantener una variable de retorno.
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);
});
}
Sin embargo, si estaba buscando algo un poco más tradicional, quizás lo siguiente sea más de su agrado.
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;
}
No tenía el problema nulo final, por lo que se eliminó para permanecer bajo par, pero debería resolverse fácilmente con un trim()
o untrimRight()
si lo prefiere, si esto le plantea un problema.
es decir.
return r.trimRight();
El resultado es una cadena de bytes ascii, si necesita unicode, lo más fácil es escape
la cadena de bytes que luego se puede decodificar decodeURIComponent
para producir la cadena unicode.
function decode_base64_usc(s) {
return decodeURIComponent(escape(decode_base64(s)));
}
Dado que escape
está en desuso, podríamos cambiar nuestra función para admitir unicode directamente sin la necesidad escape
o String.fromCharCode
podemos producir una %
cadena de escape lista para la decodificación de 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 cadena, ya que puede indexar una cadena de JavaScript como una matriz. s.split('').forEach(function ...
puede ser sustituido por [].forEach.call(s, function ...
. Debería ser mucho más rápido, ya que no tiene que dividir la cadena.
He probado las rutinas de Javascript en phpjs.org y han funcionado bien.
Primero probé las rutinas sugeridas en la respuesta elegida por Ranhiru Cooray - http://ntt.cc/2008/01/19/base64-encoder-decoder-with-javascript.html
Descubrí que no funcionaban en todas las circunstancias. Escribí un caso de prueba donde estas rutinas fallan y las publiqué en GitHub en:
https://github.com/scottcarter/base64_javascript_test_data.git
También publiqué un comentario en la publicación del blog en ntt.cc para alertar al autor (en espera de moderación; el artículo es antiguo, así que no estoy seguro de si se publicará un comentario).
En Node.js podemos hacerlo de manera simple
var base64 = 'SGVsbG8gV29ybGQ='
var base64_decode = new Buffer(base64, 'base64').toString('ascii');
console.log(base64_decode); // "Hello World"
Para frameworks JavaScripts donde no hay atob
método y en caso de que no desee importar bibliotecas externas, esta es una función corta que lo hace.
Obtendría una cadena que contiene un valor codificado en Base64 y devolverá una matriz decodificada de bytes (donde la matriz de bytes se representa como una matriz de números donde cada número es un número entero entre 0 y 255 inclusive).
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};
}
Recursos utilizados: RFC-4648 Sección 4