Português (Brasil)

Ferramentas de desenvolvedor · Codificador e decodificador Base64

O que significam atob e btoa e por que eles só entendem latim-1

· Fundo

base64 javascript Unicode

modelo de unidade de byte de string binária btoa e atob, distinto do texto Unicode
Ilustração vetorial original ToolAcre

atob e btoa datam do Netscape e os nomes significam 'ASCII para binário' e 'binário para ASCII'. Esta postagem aborda de onde eles vieram, como os padrões WHATWG os definem e por que nunca aprenderam Unicode.

Um nome de função que parece um erro de digitação - a confusão que os nomes causam e a resposta de uma linha

atob e btoa são funções integradas JavaScript que foram introduzidas no Netscape na década de 1990. Os nomes são abreviações: btoa significa binário para ASCII e atob significa ASCII para binário. Os nomes refletem sua idade e design: eles foram construídos quando binário significava uma sequência de valores de bytes (0-255) em vez do mais moderno Uint8Array ou Buffer. O mnemônico frequentemente fornecido para os nomes é menos importante que o contrato observável: uma função mapeia uma string binária para Base64 e a outra a inverte. Este repositório não documenta a decisão de nomenclatura original, portanto o artigo evita apresentar o folclore como histórico do navegador de origem.

As funções esperam uma string binária: a unidade de código de cada caractere deve estar no intervalo 0-255, representando um byte. Se você passar um caractere com uma unidade de código acima de 255 (como um emoji ou uma letra acentuada de fora do Latin-1), a função lançará InvalidCharacterError ou produzirá silenciosamente uma saída incorreta. btoa (binário para ASCII) codifica uma string binária para base64.

O que os nomes sugerem e o que o contrato de cadeia de bytes realmente prova

A entrada deve ser uma string onde cada caractere é um byte (unidade de código 0-255). btoa(hello) codifica os bytes ASCII como base64 e retorna aGVsbG8=. btoa com a letra e-acute parece funcionar porque a letra latina-1 pré-composta e-acute (U+00E9) tem uma unidade de código de 233, que está dentro de 0-255. No entanto, btoa o codifica como um único byte, 0xE9, não como os UTF-8 bytes 0xC3 0xA9 que o e-acute deve produzir. Antes das matrizes digitadas se tornarem o contêiner normal de bytes, as APIs JavaScript usavam strings cujas unidades de código representavam bytes. Esse modelo permanece visível porque btoa rejeita unidades de código acima de 255. A cronologia precisa do produto não é estabelecida por estes arquivos; o limite de falha é estabelecido por testes executáveis.

Esta corrupção silenciosa é mais perigosa que um erro: o resultado parece bom, mas está errado. atob (ASCII para binário) decodifica base64 de volta para uma string binária. atob(aGVsbG8=) retorna olá. A saída é uma string binária onde a unidade de código de cada caractere é 0-255, representando um byte. Se você deseja converter isso em texto Unicode adequado, você precisa interpretar os bytes como UTF-8 e decodificá-los com TextDecoder.

O modelo legado de string binária – comportamento observável sem uma declaração de histórico de navegador não verificada

Para ASCII, esta etapa extra é desnecessária (ASCII é um subconjunto de UTF-8), mas para quaisquer bytes não ASCII, é essencial. atob não faz essa interpretação; ele retorna os bytes brutos como uma string binária.

Os padrões WHATWG (os padrões vivos para APIs da web) definem atob e btoa na especificação HTML. A definição inclui um algoritmo de decodificação base64 indulgente para atob: ele ignora espaços em branco e aceita preenchimento ausente, tornando base64 do mundo real (incluindo base64 encapsulado em MIME com quebras de linha) decodificável. ToolAcre normaliza espaços em branco, pontuação segura URL e preenchimento ausente antes de chamar o decodificador do navegador. Em seguida, ele copia as unidades de código retornadas para Uint8Array e aplica um decodificador fatal UTF-8. Essa combinação separa a sintaxe Base64 indulgente da interpretação estrita de texto.

Comportamento atual nesta implementação - perdoando a normalização do alfabeto e a decodificação de texto estrita UTF-8

A assinatura da função não mudou, mas a definição dos padrões é a autoridade para o que a função faz. Por que atob e btoa aceitam apenas Latin-1? Porque quando foram projetados na década de 1990, JavaScript não tinha como representar bytes diretamente (sem Uint8Array ou ArrayBuffer). A única maneira de passar bytes para uma função era como uma string onde cada caractere representa um byte.

Isso é chamado de string binária e é confuso para os padrões modernos. Uma string JavaScript é um texto Unicode, não uma sequência de bytes. O design combinou os dois: uma string onde cada unidade de código é 0-255 é uma string binária. A nomenclatura reflete a época: ASCII em btoa significava literalmente sete bits para o texto ASCII, mas a implementação aceita qualquer byte (0-255). Adicionar um modo Unicode diretamente ao btoa alteraria seu contrato de cadeia de bytes de longa data e a compatibilidade de risco. A fonte revisada compõe TextEncoder antes da codificação. Este artigo pode verificar essa composição; omite afirmações sobre motivos do comitê de padrões não registrados no repositório.

Exemplo resolvido: rastreando forgiving-base64 em uma string com espaços e preenchimento ausente - o que atob aceita que um decodificador estrito rejeita

Alternativas modernas evitam o modelo de string binária. A codificação API fornece TextEncoder para converter texto em UTF-8 bytes e TextDecoder para converter UTF-8 bytes de volta em texto.

A codificação e decodificação Base64 agora são especificadas na especificação HTML para strings (atob e btoa) e matrizes digitadas. A ferramenta codificador e decodificador Base64 usa TextEncoder e TextDecoder em torno de atob e btoa, para que você possa codificar e decodificar texto Unicode com segurança sem as limitações Latin-1. Um valor espaçado ou não preenchido é bem-sucedido porque a normalização remove os espaços em branco e restaura o comprimento do bloco necessário. Um valor cujo comprimento limpo deixa o resto um é rejeitado antes de atob. Esta distinção mostra o que “perdoar” significa aqui: a formatação recuperável é aceita, mas a entrada estruturalmente impossível não é.

Os padrões mais recentes funcionam em Base64 para arrays digitados — descritos qualitativamente, com uma nota para verificar o suporte atual do navegador

O tratamento de Unicode com btoa requer a codificação do texto em UTF-8 bytes primeiro. A solução alternativa antiga era btoa(unescape(encodeURIComponent(text))), o que é confuso, mas funciona: encodeURIComponent codifica por cento UTF-8 bytes, unescape converte trigêmeos de volta em caracteres e btoa codifica a string binária resultante. Isso funciona, mas depende de funções obsoletas e é difícil de ler. O código moderno deve usar TextEncoder(text).map(byte => String.fromCharCode(byte)) seguido de btoa, ou melhor, converter diretamente para Uint8Array e usar a codificação API.

Atob não fornece texto automaticamente; isso lhe dá binário. atob(Y2Fmw6kg8J+YgA==) retorna uma string binária contendo os bytes de texto codificado em UTF-8 com acento caf e emoji. Para recuperar o texto, converta a string binária em Uint8Array e passe-a para TextDecoder(utf-8). A ferramenta codificadora e decodificadora Base64 faz isso automaticamente: você cola o texto, ela o codifica em UTF-8 bytes e depois em base64. APIs Base64 de array digitado estão evoluindo entre navegadores, mas esta fonte não as utiliza. Dependendo de um deles, é necessária uma verificação de compatibilidade atual e um plano alternativo. A conversão explícita de array de bytes de ToolAcre permanece inspecionável e coberta por seu conjunto de testes atual.

As alternativas de typed-array estão evoluindo – verifique o suporte atual do navegador antes de depender delas

Você cola base64, ele decodifica em UTF-8 bytes e depois em texto. A etapa intermediária da cadeia binária está oculta porque é um detalhe de implementação do API da década de 1990. Compreender atob e btoa é útil para depurar código legado ou trabalhar com APIs antigas que fornecem strings binárias. A maioria dos novos códigos deve evitar totalmente o modelo de string binária.

Se você precisar codificar ou decodificar base64, a ferramenta codificador e decodificador Base64 lida com Unicode corretamente. Se você estiver construindo um API, aceite Uint8Array ou uma visualização de array digitado, ou documente claramente se sua base64 é UTF-8 ou Latin-1. Ao revisar o código que usa btoa com texto não ASCII sem TextEncoder, é um bug: a saída codifica os bytes errados. O Node Buffer e os tempos de execução sem navegador definem diferentes APIs e regras de aceitação. Eles são intencionalmente excluídos. As afirmações neste artigo referem-se às primitivas do navegador e ao wrapper implementado em apps/dev, e não a todas as funções chamadas atob ou btoa em todos os ambientes.

Conclusão: duas funções da década de 1990 com um contrato de string de bytes - como o codificador e decodificador Base64 faz o UTF-8 contorná-las para que os acentos, CJK e emoji ida e volta

Os nomes atob e btoa são artefatos peculiares da computação dos anos 1990. A nomenclatura moderna seria base64Encode e base64Decode, e as APIs aceitariam Uint8Array ou strings com declarações de codificação explícitas. Mas atob e btoa persistem nos navegadores para compatibilidade com versões anteriores. Compreender o que eles significam (e o que não podem fazer) ajuda a evitar corrupção silenciosa ao codificar texto Unicode.

A ferramenta codificadora e decodificadora Base64 preenche a lacuna: ela fala as linguagens UTF-8 e base64 que o código moderno precisa. O padrão robusto é composicional: codifique o texto em UTF-8 bytes, converta os bytes no contrato de string binária e, em seguida, chame btoa; inverta essas etapas em torno de atob. Experimente um sotaque, CJK caracteres e emoji e, em seguida, exija que o texto decodificado corresponda a cada ponto de código original.