Pesquisa de site

Codificação e decodificação Base64 em Javascript do lado do cliente


Existem métodos em JavaScript que podem ser usados para codificar e decodificar uma string usando codificação base64?

Resposta #1

Alguns navegadores como Firefox, Chrome, Safari, Opera e IE10+ podem lidar com Base64 nativamente. Dê uma olhada nesta pergunta do Stackoverflow. Está usando as funções btoa() e atob().

Para JavaScript do lado do servidor (Node), você pode usar Buffers para decodificar.

Se você está procurando uma solução compatível com vários navegadores, existem bibliotecas existentes como CryptoJS ou código como:

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

Com o último, você precisa testar a função minuciosamente para compatibilidade entre navegadores. E um erro já foi relatado.

Resposta #2

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

Cross-Browser

Bibliotecas/Módulos de Codificação e Decodificação UTF-8 e Base64 em Javascript reescritas e moduladas para AMD, CommonJS, Nodejs e navegadores. Compatível com múltiplos navegadores.


com Node.js

Aqui está como você codifica texto normal em 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 = Buffer.from('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 decodificar strings codificadas em base64:

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

com Dojo.js

Para codificar um array de bytes usando dojox.encoding.base64:

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

Para decodificar uma string codificada em base64:

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

bower install angular-base64

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

Mas como?

Se você gostaria de aprender mais sobre como o base64 é codificado em geral, e em JavaScript em particular, eu recomendaria este artigo: Ciência da computação em JavaScript: Codificação Base64

Resposta #3

Em navegadores baseados em Gecko/WebKit (Firefox, Chrome e Safari) e Opera, você pode usar btoa() e atob().

Resposta original: Como você pode codificar uma string em Base64 no JavaScript?

Resposta #4

Aqui está uma versão mais enxuta do post do Sniper. Ela presume uma string base64 bem formada, sem quebras de linha. Esta versão elimina alguns loops, adiciona o ajuste &0xff do Yaroslav, elimina nulos finais, além de um pouco de otimização de código.

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

Resposta #5

Função curta e rápida de decodificação Base64 em JavaScript sem proteção contra 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;
}

Resposta #6

Navegadores modernos têm funções JavaScript integradas para codificação Base64 btoa() e decodificação atob(). Mais informações sobre suporte em versões mais antigas de navegadores: https://caniuse.com/?search=atob

No entanto, fique ciente de que as funções atob e btoa funcionam apenas para o charset ASCII. Se você precisar de funções Base64 para o charset UTF-8, você pode fazer isso com:

function base64_encode(s) {      
    return btoa(unescape(encodeURIComponent(s)));
}
function base64_decode(s) {      
    return decodeURIComponent(escape(atob(s)));
}

Resposta #7

function b64_to_utf8( str ) {
  return decodeURIComponent(escape(window.atob( str )));
}

https://developer.mozilla.org/pt-BR/docs/Web/API/WindowBase64/Base64_encoding_and_decoding#O_.22Problema_do_Unicode.22

Resposta #8

Alguém disse code golf? =)

O seguinte é minha tentativa de melhorar meu handicap enquanto me atualizo com os tempos. 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;
}

O que eu realmente procurava era uma implementação assíncrona e, para minha surpresa, descobri que forEach, ao contrário da implementação do método $ ([]).each do JQuery, é bastante síncrona.

Se você também tivesse tais noções loucas em mente, um window.setTimeout com atraso 0 executará a decodificação base64 de forma assíncrona e chamará 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);
}

@Toothbrush sugeriu "indexar uma string como um array" e se livrar do split. Esta rotina parece realmente estranha e não tenho certeza de quão compatível será, mas ela pega outro ponto, então vamos adotá-la.

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

Enquanto tentava encontrar mais informações sobre string em JavaScript como array, deparei-me com esta dica profissional usando uma regex /./g para percorrer uma string. Isso reduz ainda mais o tamanho do código, substituindo a string no local 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 do 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;
}

Eu não tive o problema do null no final, então isso foi removido para permanecer dentro do padrão, mas isso deve ser facilmente resolvido com um trim() ou um trimRight() se você preferir, caso isso represente um problema para você.

ou seja

return r.trimRight();

Nota :

O resultado é uma string de bytes ASCII, se você precisar de Unicode, o mais fácil é escape a string de bytes, que então pode ser decodificada com decodeURIComponent para produzir a string Unicode.

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

Como escape está sendo descontinuado, poderíamos alterar nossa função para suportar Unicode diretamente, sem a necessidade de escape ou String.fromCharCode, podemos produzir uma string com % escapada pronta para decodificação 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);
  }));
}

Editar para @Charles Byrne:

Não consigo lembrar por que não ignoramos os caracteres de preenchimento '='; talvez tenha funcionado com uma especificação que não os exigia na época. Se modificássemos a rotina decodeURIComponent para ignorá-los, como deveríamos já que eles não representam nenhum dado, o resultado decodificaria o exemplo corretamente.

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

Agora, chamar decode_base64('4pyTIMOgIGxhIG1vZGU=') retornará a string codificada '✓ à la mode', sem nenhum erro.

Como '=' é reservado como caractere de preenchimento, posso reduzir minha desvantagem no code golf, se me permitem:

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||'='==v?'':'%'+(0x100+((b>>>(l-=8))&0xff)).toString(16).slice(-2);
  }));
}

Aproveite!

Resposta #9

O projeto php.js possui implementações em JavaScript de muitas funções do PHP. base64_encode e base64_decode estão incluídas.

Resposta #10

Para o que vale, eu me inspirei nas outras respostas e escrevi uma pequena utilidade que chama as APIs específicas da plataforma para ser usada universalmente tanto no Node.js quanto em um navegador:

/**
 * Encode a string of text as base64
 *
 * @param data The string of text.
 * @returns The base64 encoded string.
 */
function encodeBase64(data: string) {
    if (typeof btoa === "function") {
        return btoa(data);
    } else if (typeof Buffer === "function") {
        return Buffer.from(data, "utf-8").toString("base64");
    } else {
        throw new Error("Failed to determine the platform specific encoder");
    }
}

/**
 * Decode a string of base64 as text
 *
 * @param data The string of base64 encoded text
 * @returns The decoded text.
 */
function decodeBase64(data: string) {
    if (typeof atob === "function") {
        return atob(data);
    } else if (typeof Buffer === "function") {
        return Buffer.from(data, "base64").toString("utf-8");
    } else {
        throw new Error("Failed to determine the platform specific decoder");
    }
}

Artigos relacionados