Lorsque vous utilisez atob pour décoder les chaînes de réponse API des services qui génèrent leur sortie en UTF-8, vous pouvez rencontrer des erreurs ou des encodages de chaînes cassés. Cela est dû aux limitations de la gestion base64 de JavaScript :
<code class="js">const notOK = "✓" console.log(btoa(notOK)); // error</code>
Même après que cette erreur ait été résolue dans ECMAScript, le « problème Unicode » demeure, car base64 est un binaire format qui suppose que chaque caractère codé occupe un seul octet. De nombreux caractères Unicode nécessitent plus d'un octet pour être encodés, ce qui peut entraîner des échecs d'encodage.
Source : MDN (2021)
<code class="js">const ok = "a"; console.log(ok.codePointAt(0).toString(16)); // 0x61: occupies 1 byte const notOK = "✓"; console.log(notOK.codePointAt(0).toString(16)); // 0x2713: occupies 2 bytes</code>
Si vous ne savez pas quelle solution choisir, c'est probablement celle que vous souhaitez. Continuez à faire défiler la page pour trouver la solution ASCII base64 et l'historique de cette réponse.
Envisagez d'utiliser une approche binaire en convertissant les chaînes UTF-8 en représentations binaires et vice versa.
<code class="js">function toBinary(string) { const codeUnits = new Uint16Array(string.length); for (let i = 0; i < codeUnits.length; i++) { codeUnits[i] = string.charCodeAt(i); } return btoa(String.fromCharCode(...new Uint8Array(codeUnits.buffer))); } encoded = toBinary("✓ à la mode") // "EycgAOAAIABsAGEAIABtAG8AZABlAA=="</code>
<code class="js">function fromBinary(encoded) { const binary = atob(encoded); const bytes = new Uint8Array(binary.length); for (let i = 0; i < bytes.length; i++) { bytes[i] = binary.charCodeAt(i); } return String.fromCharCode(...new Uint16Array(bytes.buffer)); } decoded = fromBinary(encoded) // "✓ à la mode"</code>
Pour préserver la fonctionnalité UTF-8, une autre approche à travers L'interopérabilité ASCII base64 est recommandée, ce qui résout "Le problème Unicode" tout en maintenant la compatibilité avec les chaînes texte base64.
<code class="js">function b64EncodeUnicode(str) { // Percent-encode Unicode, then convert to byte array return btoa(encodeURIComponent(str).replace(/%([0-9A-F]{2})/g, function(match, p1) { return String.fromCharCode('0x' + p1); })); } b64EncodeUnicode('✓ à la mode'); // "4pyTIMOgIGxhIG1vZGU="</code>
<code class="js">function b64DecodeUnicode(str) { // Convert byte array to percent-encoding, then decode return decodeURIComponent(atob(str).split('').map(function(c) { return '%' + ('00' + c.charCodeAt(0).toString(16)).slice(-2); }).join('')); } b64DecodeUnicode('4pyTIMOgIGxhIG1vZGU='); // "✓ à la mode"</code>
<code class="ts">function b64EncodeUnicode(str) { return btoa(encodeURIComponent(str).replace(/%([0-9A-F]{2})/g, function(match, p1) { return String.fromCharCode(parseInt(p1, 16)) })) } function b64DecodeUnicode(str) { return decodeURIComponent(Array.prototype.map.call(atob(str), function(c) { return '%' + ('00' + c.charCodeAt(0).toString(16)).slice(-2) }).join('')) }</code>
Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!