Herramientas de desarrollo · Codificador y decodificador Base64
Qué significan atob y btoa y por qué solo entienden latín-1
· Antecedentes
base64 javascript Unicode
atob y btoa datan de Netscape y los nombres significan 'ASCII a binario' y 'binario a ASCII'. Esta publicación cubre de dónde vienen, cómo los definen los estándares WHATWG y por qué nunca aprendieron Unicode.
Un nombre de función que se lee como un error tipográfico: la confusión que causan los nombres y la respuesta de una sola línea
atob y btoa son funciones integradas de JavaScript que se introdujeron en Netscape en la década de 1990. Los nombres son abreviaturas: btoa significa binario a ASCII y atob significa ASCII a binario. Los nombres reflejan su antigüedad y diseño: se crearon cuando binario significaba una cadena de valores de bytes (0-255) en lugar de los más modernos Uint8Array o Buffer. El mnemotécnico que a menudo se da para los nombres es menos importante que el contrato observable: una función asigna una cadena binaria a Base64 y la otra la invierte. Este repositorio no documenta la decisión de nomenclatura original, por lo que el artículo evita presentar el folclore como historial del navegador.
Las funciones esperan una cadena binaria: la unidad de código de cada carácter debe estar en el rango 0-255, lo que representa un byte. Si pasa un carácter con una unidad de código superior a 255 (como un emoji o una letra acentuada fuera del latín-1), la función arroja InvalidCharacterError o produce silenciosamente una salida incorrecta. btoa (binario a ASCII) codifica una cadena binaria en base64.
Lo que sugieren los nombres y lo que realmente demuestra el contrato de cadena de bytes
La entrada debe ser una cadena donde cada carácter es un byte (unidad de código 0-255). btoa(hola) codifica los bytes ASCII como base64 y devuelve aGVsbG8=. btoa con la letra e-acute parece funcionar porque la letra latina-1 precompuesta e-acute (U+00E9) tiene una unidad de código de 233, que está dentro de 0-255. Sin embargo, btoa lo codifica como un solo byte, 0xE9, no los UTF-8 bytes 0xC3 0xA9 que debería producir e-acute. Antes de que las matrices escritas se convirtieran en el contenedor de bytes normal, las API de JavaScript usaban cadenas cuyas unidades de código representaban bytes. Ese modelo permanece visible porque btoa rechaza unidades de código superiores a 255. Estos archivos no establecen la cronología precisa del producto; el límite de falla se establece mediante pruebas ejecutables.
Esta corrupción silenciosa es más peligrosa que un error: el resultado parece correcto pero es incorrecto. atob (ASCII a binario) decodifica base64 a una cadena binaria. atob(aGVsbG8=) devuelve hola. La salida es una cadena binaria donde la unidad de código de cada carácter es 0-255, lo que representa un byte. Si desea convertir esto a texto Unicode adecuado, debe interpretar los bytes como UTF-8 y decodificarlos con TextDecoder.
El modelo de cadena binaria heredado: comportamiento observable sin una afirmación del historial del navegador no verificada
Para ASCII, este paso adicional es innecesario (ASCII es un subconjunto de UTF-8), pero para cualquier byte que no sea ASCII, es esencial. atob no hace esa interpretación; devuelve los bytes sin formato como una cadena binaria.
Los estándares WHATWG (los estándares de vida para las API web) definen atob y btoa en la especificación HTML. La definición incluye un algoritmo de decodificación de base64 indulgente para atob: omite espacios en blanco y acepta el relleno faltante, lo que hace que base64 del mundo real (incluido base64 envuelto en MIME con saltos de línea) sea decodificable. ToolAcre normaliza los espacios en blanco, la puntuación segura para URL y el relleno faltante antes de llamar al decodificador del navegador. Luego copia las unidades de código devueltas en Uint8Array y aplica un decodificador fatal UTF-8. Esa combinación separa la sintaxis Base64 tolerante de la interpretación estricta del texto.
Comportamiento actual en esta implementación: tolerancia a la normalización del alfabeto y estricta decodificación de texto UTF-8
La firma de la función no ha cambiado, pero la definición de estándares es la autoridad para lo que hace la función. ¿Por qué atob y btoa solo aceptan Latin-1? Porque cuando se diseñaron en la década de 1990, JavaScript no tenía una forma de representar bytes directamente (ni Uint8Array ni ArrayBuffer). La única forma de pasar bytes a una función era como una cadena donde cada carácter representa un byte.
Esto se llama cadena binaria y resulta confuso según los estándares modernos. Una cadena de JavaScript es texto Unicode, no una secuencia de bytes. El diseño combinó los dos: una cadena donde cada unidad de código es 0-255 es una cadena binaria. El nombre refleja la época: ASCII en btoa significaba literalmente siete bits para texto ASCII, pero la implementación acepta cualquier byte (0-255). Agregar un modo Unicode directamente a btoa cambiaría su contrato de cadena de bytes de larga data y su compatibilidad de riesgos. En cambio, la fuente revisada compone TextEncoder antes de codificar. Este artículo puede comprobar esa composición; omite afirmaciones sobre motivos del comité de normas que no están registrados en el repositorio.
Ejemplo resuelto: seguimiento de perdonar-base64 en una cadena con espacios y falta relleno: lo que atob acepta y que un decodificador estricto rechaza
Las alternativas modernas evitan el modelo de cadena binaria. La API de codificación proporciona TextEncoder para convertir texto a UTF-8 bytes y TextDecoder para convertir UTF-8 bytes nuevamente a texto.
La codificación y decodificación Base64 ahora se especifica en la especificación HTML tanto para cadenas (atob y btoa) como para matrices escritas. La herramienta de codificación y descodificación Base64 utiliza TextEncoder y TextDecoder en torno a atob y btoa, por lo que puede codificar y decodificar texto Unicode de forma segura sin las limitaciones de Latin-1. Un valor espaciado o sin relleno tiene éxito porque la normalización elimina los espacios en blanco y restaura la longitud de bloque requerida. Un valor cuya longitud limpia deja el resto uno se rechaza antes de atob. Esta distinción muestra lo que aquí significa "perdonar": se acepta el formato recuperable, pero no la entrada estructuralmente imposible.
Los estándares más nuevos funcionan en Base64 para matrices escritas: se describen cualitativamente, con una nota para verificar la compatibilidad actual del navegador.
El manejo de Unicode con btoa requiere codificar el texto en UTF-8 bytes primero. La antigua solución era btoa(unescape(encodeURIComponent(texto))), que es confusa pero funciona: encodeURIComponent codifica por ciento UTF-8 bytes, unescape vuelve a convertir tripletes en caracteres y btoa codifica la cadena binaria resultante. Esto funciona pero depende de funciones obsoletas y es difícil de leer. El código moderno debe usar TextEncoder(text).map(byte => String.fromCharCode(byte)) seguido de btoa, o mejor, convertir directamente a Uint8Array y usar la API de codificación.
Atob no le proporciona mensajes de texto automáticamente; te da binario. atob(Y2Fmw6kg8J+YgA==) devuelve una cadena binaria que contiene los bytes de texto codificado UTF-8 con acento caf y emoji. Para recuperar el texto, convierta la cadena binaria a Uint8Array y pásela a TextDecoder(utf-8). La herramienta codificadora y decodificadora Base64 hace esto automáticamente: pegas texto, lo codifica en UTF-8 bytes y luego en base64. Las API Base64 de matriz escrita están evolucionando en todos los navegadores, pero esta fuente no las utiliza. Dependiendo de uno, se requiere una verificación de compatibilidad actual y un plan alternativo. La conversión explícita de matrices de bytes de ToolAcre sigue siendo inspeccionable y cubierta por su conjunto de pruebas actual.
Las alternativas de matriz escrita están evolucionando: verifique la compatibilidad actual del navegador antes de depender de ellas
Pegas base64, se decodifica en UTF-8 bytes y luego en texto. El paso intermedio de cadena binaria está oculto porque es un detalle de implementación de la API de los años 90. Comprender atob y btoa es útil para depurar código heredado o trabajar con API antiguas que proporcionan cadenas binarias. La mayoría del código nuevo debería evitar por completo el modelo de cadena binaria.
Si necesita codificar o decodificar base64, la herramienta codificadora y decodificadora Base64 maneja Unicode correctamente. Si está creando una API, acepte Uint8Array o una vista de matriz escrita, o documente claramente si su base64 es UTF-8 o Latin-1. Al revisar el código que usa btoa con texto que no es ASCII sin TextEncoder, se produce un error: la salida codifica los bytes incorrectos. Los tiempos de ejecución de Node Buffer y sin navegador definen diferentes API y reglas de aceptación. Están excluidos intencionalmente. Las afirmaciones de este artículo se refieren a las primitivas del navegador y al contenedor implementado en apps/dev,, no a todas las funciones denominadas atob o btoa en todos los entornos.
Conclusión: dos funciones de la década de 1990 con un contrato de cadena de bytes: cómo el codificador y descodificador Base64 hace que el UTF-8 las evite para que los acentos, CJK y emoji ida y vuelta
Los nombres atob y btoa son artefactos peculiares de la informática de los años 90. Los nombres modernos serían base64Encode y base64Decode, y las API aceptarían Uint8Array o cadenas con declaraciones de codificación explícitas. Pero atob y btoa persisten en los navegadores por motivos de compatibilidad con versiones anteriores. Comprender lo que significan (y lo que no pueden hacer) le ayudará a evitar una corrupción silenciosa al codificar texto Unicode.
La herramienta de codificación y decodificación Base64 cierra la brecha: habla los lenguajes UTF-8 y base64 que el código moderno necesita. El patrón robusto es compositivo: codifica texto en UTF-8 bytes, convierte bytes al contrato de cadena binaria y luego llama a btoa; invierta esos pasos alrededor de atob. Pruebe con un acento, caracteres CJK y emoji, luego solicite que el texto decodificado coincida con cada punto del código original.