Cuando Base64 parece "romper el chino", el problema suele ser el límite entre caracteres y bytes. Base64 no sabe que una secuencia representa texto chino o emoji. Conserva bytes; la aplicación elige cómo se producen e interpretan esos bytes.
Sigue los bytes
El carácter 中 es U+4E2D. En UTF-8 utiliza los bytes E4 B8 AD, cuya representación Base64 es 5Lit. Una codificación de caracteres diferente produce bytes diferentes y, por lo tanto, un valor Base64 diferente. Acuerde UTF-8 en ambos extremos antes de comparar cadenas codificadas.
const bytes = new TextEncoder().encode('中');
console.log([...bytes]); // [228, 184, 173]
console.log([...bytes].map(b => b.toString(16)).join(' ')); // e4 b8 ad
Los emoji ilustran otra distinción: JavaScript '😊'.length son dos unidades de código UTF-16, mientras que su representación UTF-8 tiene cuatro bytes. Ninguno de los números por sí solo es un recuento de caracteres visibles percibidos por el usuario en texto arbitrario. Utilice la longitud en bytes para cálculos de archivos y transporte.
Hacer visible el reemplazo
El carácter de reemplazo � puede significar que un decodificador anterior ya perdió información. Una vez que los bytes desconocidos se han reemplazado en una cadena y esa cadena se vuelve a codificar, los valores originales generalmente no se pueden reconstruir. Inspeccione la matriz de bytes decodificados sin procesar antes de realizar más conversiones.
const decoder = new TextDecoder('utf-8', { fatal: true });
console.log(decoder.decode(Uint8Array.of(0xe4, 0xb8, 0xad))); // 中
try { decoder.decode(Uint8Array.of(0xff)); }
catch { console.log('Invalid UTF-8; preserve the original byte.'); }
La normalización es una operación separada.
Dos cadenas pueden parecer idénticas aunque contengan diferentes secuencias Unicode. La letra é acentuada puede ser un carácter precompuesto o una e seguida de un acento combinado. UTF-8 y Base64 conservan correctamente esa diferencia. Si su aplicación quiere texto normalizado, elija una forma de normalización explícitamente y aplíquela antes de codificar; nunca llame a un resultado modificado una reparación que preserva los bytes.
Compruebe también los caracteres invisibles, los finales de línea y una posible marca de orden de bytes cuando los resultados difieran. Estos son bytes de entrada reales, no necesariamente errores del codificador. Para mensajes firmados y sumas de verificación, incluso una diferencia invisible cambia el resultado.
Un orden confiable de solución de problemas es: preservar el origen, inspeccionar bytes, identificar la codificación de caracteres esperada, decodificar con manejo explícito de errores y solo entonces considerar la normalización. MDN: btoa() explica por qué las llamadas btoa directas del navegador no son adecuadas para texto Unicode arbitrario. Los archivos binarios deberían omitir por completo la decodificación de texto.