Existem métodos em JavaScript que podem ser usados para codificar e decodificar uma string usando a codificação base64?
Existem métodos em JavaScript que podem ser usados para codificar e decodificar uma string usando a codificação base64?
Respostas:
Alguns navegadores como Firefox, Chrome, Safari, Opera e IE10 + podem lidar com o Base64 nativamente. Dê uma olhada nesta pergunta do Stackoverflow . Está usando btoa()
e atob()
funções .
Para JavaScript do lado do servidor (Nó), você pode usar Buffer
s para decodificar.
Se você está procurando uma solução entre navegadores, existem bibliotecas existentes como o CryptoJS ou código como:
http://ntt.cc/2008/01/19/base64-encoder-decoder-with-javascript.html
Com o último, você precisa testar minuciosamente a função para compatibilidade entre navegadores. E o erro já foi relatado .
new Buffer('Hello, world!').toString('base64');
new Buffer('SGVsbG8sIHdvcmxkIQ==', 'base64').toString('ascii');
(fonte)
new Buffer(string)
está obsoleto. Buffer.from(jwt.split('.')[1], 'base64').toString()
Nos navegadores baseados no Gecko / WebKit (Firefox, Chrome e Safari) e no Opera, você pode usar btoa () e atob () .
Resposta original: Como você pode codificar uma string para Base64 em 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!"
Aqui está como você codifica o texto normal para base64 no 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');
E aqui está como você decodifica cadeias codificadas em base64:
var b = new Buffer('SmF2YVNjcmlwdA==', 'base64')
var s = b.toString();
Para codificar uma matriz de bytes usando dojox.encoding.base64:
var str = dojox.encoding.base64.encode(myByteArray);
Para decodificar uma sequência codificada em 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 você quiser saber mais sobre como a base64 é codificada em geral e em JavaScript em particular, eu recomendaria este artigo: Ciência da computação em JavaScript: codificação Base64
c2
e provável c1
e c3
por isso não irá trabalhar com "use strict"
como definido acima.
Aqui está uma versão mais rigorosa do post de Sniper. Ele pressupõe uma string base64 bem formada, sem retornos de carro. Esta versão elimina alguns loops, adiciona a &0xff
correção de Yaroslav, elimina valores nulos à direita, além de um pouco de código de golfe.
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++;
Função de decodificação de JavaScript Base64 curta e rápida, sem falhas:
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 )));
}
O projeto php.js possui implementações em JavaScript de muitas das funções do PHP. base64_encode
e base64_decode
estão incluídos.
Alguém disse código de golfe? =)
A seguir, é minha tentativa de melhorar minha desvantagem enquanto acompanho os horários. Fornecido para sua conveniência.
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;
}
Na verdade, o que eu procurava era uma implementação assíncrona e, para minha surpresa, ao forEach
contrário da $([]).each
implementação do método JQuery, é muito síncrona.
Se você também tiver em mente essas noções malucas, um atraso 0 window.setTimeout
executará a decodificação da base64 de forma assíncrona e executará a função de retorno de chamada com o resultado quando terminar.
function decode_base64_async(s, cb) {
setTimeout(function () { cb(decode_base64(s)); }, 0);
}
A @ Toothbrush sugeriu "indexar uma string como uma matriz" e se livrar do split
. Essa rotina parece realmente estranha e não tem certeza de quão compatível será, mas atinge outro passarinho, então vamos lá.
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;
}
Ao tentar encontrar mais informações sobre a string JavaScript como array, eu tropecei nesta dica profissional usando um /./g
regex para percorrer uma string. Isso reduz ainda mais o tamanho do código, substituindo a string no lugar e eliminando a necessidade de manter uma variável 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);
});
}
Se, no entanto, você estava procurando algo um pouco mais tradicional, talvez o seguinte seja mais para o seu gosto.
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;
}
Como não havia o problema nulo à direita, ele foi removido para permanecer abaixo do padrão, mas deve ser facilmente resolvido com um trim()
ou umtrimRight()
se você preferir, caso isso represente um problema para você.
ie
return r.trimRight();
O resultado é uma sequência de bytes ascii, se você precisar de unicode, o mais fácil é a escape
sequência de bytes que pode ser decodificada decodeURIComponent
para produzir a sequência de caracteres unicode.
function decode_base64_usc(s) {
return decodeURIComponent(escape(decode_base64(s)));
}
Como escape
está sendo descontinuado, podemos alterar nossa função para oferecer suporte a unicode diretamente sem a necessidade escape
ou String.fromCharCode
podemos produzir uma %
string de escape pronta para decodificação 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
da string, pois pode indexar uma string JavaScript como uma matriz. s.split('').forEach(function ...
pode ser substituído por [].forEach.call(s, function ...
. Deve ser muito mais rápido, porque não é necessário dividir a string.
Eu tentei as rotinas Javascript em phpjs.org e elas funcionaram bem.
Tentei pela primeira vez as rotinas sugeridas na resposta escolhida por Ranhiru Cooray - http://ntt.cc/2008/01/19/base64-encoder-decoder-with-javascript.html
Eu descobri que eles não funcionavam em todas as circunstâncias. Eu escrevi um caso de teste em que essas rotinas falham e as postei no GitHub em:
https://github.com/scottcarter/base64_javascript_test_data.git
Também publiquei um comentário no blog no ntt.cc para alertar o autor (aguardando moderação - o artigo é antigo, portanto não tenho certeza se o comentário será publicado).
No Node.js, podemos fazê-lo de maneira simples
var base64 = 'SGVsbG8gV29ybGQ='
var base64_decode = new Buffer(base64, 'base64').toString('ascii');
console.log(base64_decode); // "Hello World"
Para estruturas JavaScripts em que não há atob
método e, caso você não queira importar bibliotecas externas, esta é uma função curta.
Ele obteria uma string que contém o valor codificado em Base64 e retornará uma matriz decodificada de bytes (onde a matriz de bytes é representada como matriz de números em que cada número é um número inteiro entre 0 e 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 Seção 4