Estoy usando la window.atob()
función Javascript para decodificar una cadena codificada en base64 (específicamente el contenido codificado en base64 de la API de GitHub). El problema es que estoy recuperando caracteres codificados en ASCII (como en â¢
lugar de ™
). ¿Cómo puedo manejar correctamente la transmisión entrante codificada en base64 para que se decodifique como utf-8?
javascript
encoding
utf-8
brandonscript
fuente
fuente
atob
Respuestas:
Hay un gran artículo sobre los documentos MDN de Mozilla que describe exactamente este problema:
Una nota sobre soluciones anteriores: el artículo de MDN sugirió originalmente usar
unescape
yescape
para resolver el problema de laCharacter Out Of Range
excepción, pero desde entonces han quedado obsoletos. Algunas otras respuestas aquí han sugerido trabajar en torno a esto condecodeURIComponent
yencodeURIComponent
, esto ha demostrado ser poco confiable e impredecible. La actualización más reciente de esta respuesta utiliza funciones de JavaScript modernas para mejorar la velocidad y modernizar el código.Si está tratando de ahorrar algo de tiempo, también podría considerar usar una biblioteca:
Codificación UTF8 ⇢ base64
Decodificación base64 ⇢ UTF8
La solución anterior a 2018 (funcional, y aunque probablemente mejor soporte para navegadores más antiguos, no actualizada)
Aquí está la recomendación actual, directa de MDN, con compatibilidad adicional con TypeScript a través de @ MA-Maddin:
La solución original (obsoleta)
Este usado
escape
yunescape
(que ahora está en desuso, aunque esto todavía funciona en todos los navegadores modernos):Y una última cosa: encontré este problema por primera vez al llamar a la API de GitHub. Para que esto funcione correctamente en Safari (móvil), tuve que eliminar todos los espacios en blanco de la fuente base64 antes de poder decodificar la fuente. Si esto sigue siendo relevante o no en 2017, no lo sé:
fuente
b64DecodeUnicode('4pyTIMOgIGxhIG1vZGU=');
ahoradecodeURIComponent(atob('4pyTIMOgIGxhIG1vZGU=').split('').map(x => '%' + x.charCodeAt(0).toString(16)).join(''))
No es el código de mayor rendimiento, pero es lo que es.return String.fromCharCode(parseInt(p1, 16));
tener compatibilidad con TypeScript.Las cosas cambian. Los métodos de escape / unescape han quedado obsoletos.
Puede codificar la cadena con URI antes de codificarla en Base64. Tenga en cuenta que esto no produce UTF8 codificado en Base64, sino datos codificados con URL codificados en Base64. Ambas partes deben acordar la misma codificación.
Vea el ejemplo de trabajo aquí: http://codepen.io/anon/pen/PZgbPW
Para el problema de OP, una biblioteca de terceros como js-base64 debería resolver el problema.
fuente
Si lo suyo es tratar las cadenas como bytes, puede utilizar las siguientes funciones
fuente
Aquí está la solución actualizada de 2018 como se describe en los Recursos de desarrollo de Mozilla
PARA CODIFICAR DE UNICODE A B64
PARA DECODIFICAR DE B64 A UNICODE
fuente
El artículo completo que me funciona: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Base64_encoding_and_decoding
La parte donde codificamos desde Unicode / UTF-8 es
Este es uno de los métodos más utilizados en la actualidad.
fuente
Asumiría que uno podría querer una solución que produzca un URI base64 ampliamente utilizable. Visite
data:text/plain;charset=utf-8;base64,4pi44pi54pi64pi74pi84pi+4pi/
para ver una demostración (copie la uri de datos, abra una nueva pestaña, pegue la URI de datos en la barra de direcciones y luego presione Intro para ir a la página). A pesar de que este URI está codificado en base64, el navegador aún puede reconocer los puntos de código alto y decodificarlos correctamente. El codificador + decodificador minificado es 1058 bytes (+ Gzip → 589 bytes)A continuación se muestra el código fuente utilizado para generarlo.
Luego, para decodificar los datos base64, HTTP obtiene los datos como un URI de datos o usa la función a continuación.
La ventaja de ser más estándar es que este codificador y este descodificador son más aplicables porque se pueden usar como una URL válida que se muestra correctamente. Observar.
Además de estar muy estandarizados, los fragmentos de código anteriores también son muy rápidos. En lugar de una cadena de sucesión indirecta en la que los datos tienen que convertirse varias veces entre varias formas (como en la respuesta de Riccardo Galli), el fragmento de código anterior es tan directo como sea posible. Utiliza solo una
String.prototype.replace
llamada rápida simple para procesar los datos al codificar, y solo una para decodificar los datos al decodificar. Otra ventaja es que (especialmente para cadenas grandes),String.prototype.replace
permite que el navegador maneje automáticamente la gestión de la memoria subyacente para cambiar el tamaño de la cadena, lo que genera un aumento significativo del rendimiento, especialmente en navegadores perennes como Chrome y Firefox que optimizan en gran medidaString.prototype.replace
. Finalmente, la guinda del pastel es que, para los usuarios de exclūsīvō de escritura latina, las cadenas que no contienen puntos de código por encima de 0x7f son más rápidas de procesar porque la cadena no se modifica por el algoritmo de reemplazo.He creado un repositorio de github para esta solución en https://github.com/anonyco/BestBase64EncoderDecoder/
fuente
La corrección pequeña, la eliminación de escape y el escape están en desuso, por lo que:
fuente
encodeURIComponent
es lodecodeURIComponent
contrario de , es decir, simplemente deshará la conversión. Consulte stackoverflow.com/a/31412163/1534459 para obtener una gran explicación de lo que está sucediendo conescape
yunescape
.encodeURIComponent
se usa es para manejar correctamente (todo el rango de) cadenas Unicode. Entonces, por ejemplo,window.btoa(decodeURIComponent(encodeURIComponent('€')))
daError: String contains an invalid character
porque es lo mismo quewindow.btoa('€')
ybtoa
no puede codificar€
.Aquí hay un código a prueba de futuro para los navegadores que pueden faltar
escape/unescape()
. Tenga en cuenta que IE 9 y versiones anteriores no son compatiblesatob/btoa()
, por lo que deberá usar funciones personalizadas de base64 para ellos.Puede encontrar un ejemplo más completo de codificación y decodificación UTF-8 aquí: http://jsfiddle.net/47zwb41o/
fuente
incluida la solución anterior, si aún enfrenta el problema, intente lo siguiente, considere el caso en el que el escape no es compatible con TS.
para csv_content puedes probar como se muestra a continuación.
fuente