J'utilise la window.atob()
fonction Javascript pour décoder une chaîne encodée en base64 (en particulier le contenu encodé en base64 de l'API GitHub). Le problème est que je récupère les caractères encodés en ASCII (comme â¢
au lieu de ™
). Comment puis-je gérer correctement le flux entrant encodé en base64 pour qu'il soit décodé en utf-8?
javascript
encoding
utf-8
brandonscript
la source
la source
atob
Réponses:
Il existe un excellent article sur la documentation MDN de Mozilla qui décrit exactement ce problème:
Une note sur les solutions précédentes: l'article de MDN suggérait à l'origine d'utiliser
unescape
etescape
de résoudre lesCharacter Out Of Range
problème d'exception, mais ils sont depuis obsolètes. Certaines autres réponses ici ont suggéré de contourner ce problème avecdecodeURIComponent
etencodeURIComponent
, cela s'est avéré peu fiable et imprévisible. La mise à jour la plus récente de cette réponse utilise des fonctions JavaScript modernes pour améliorer la vitesse et moderniser le code.Si vous essayez de gagner du temps, vous pouvez également envisager d'utiliser une bibliothèque:
Encodage UTF8 ⇢ base64
Décodage base64 ⇢ UTF8
La solution pré-2018 (fonctionnelle, et bien que probablement meilleure prise en charge pour les navigateurs plus anciens, pas à jour)
Voici la recommandation actuelle, directement de MDN, avec une compatibilité TypeScript supplémentaire via @ MA-Maddin:
La solution d'origine (obsolète)
Ceci utilisé
escape
etunescape
(qui sont maintenant obsolètes, bien que cela fonctionne toujours dans tous les navigateurs modernes):Et une dernière chose: j'ai rencontré ce problème pour la première fois lors de l'appel de l'API GitHub. Pour que cela fonctionne correctement sur Safari (Mobile), j'ai dû supprimer tout l'espace blanc de la source base64 avant même de pouvoir décoder la source. Que ce soit toujours d'actualité ou non en 2017, je ne sais pas:
la source
b64DecodeUnicode('4pyTIMOgIGxhIG1vZGU=');
decodeURIComponent(atob('4pyTIMOgIGxhIG1vZGU=').split('').map(x => '%' + x.charCodeAt(0).toString(16)).join(''))
pas le code le plus performant, mais c'est ce qu'il est.return String.fromCharCode(parseInt(p1, 16));
pour avoir la compatibilité TypeScript.Les choses changent. Les méthodes escape / unescape sont obsolètes.
Vous pouvez encoder la chaîne par URI avant de l'encoder en Base64. Notez que cela ne produit pas de données UTF8 encodées en Base64, mais plutôt des données encodées en URL encodées en Base64. Les deux parties doivent s'entendre sur le même encodage.
Voir l'exemple de travail ici: http://codepen.io/anon/pen/PZgbPW
Pour le problème d'OP, une bibliothèque tierce telle que js-base64 devrait résoudre le problème.
la source
Si vous préférez traiter les chaînes comme des octets, vous pouvez utiliser les fonctions suivantes
la source
Voici la solution mise à jour 2018 telle que décrite dans les ressources de développement de Mozilla
POUR ENCODER DE UNICODE À B64
POUR DÉCODER DE B64 À UNICODE
la source
L'article complet qui fonctionne pour moi: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Base64_encoding_and_decoding
La partie où nous encodons à partir d'Unicode / UTF-8 est
C'est l'une des méthodes les plus utilisées de nos jours.
la source
Je suppose que l'on pourrait vouloir une solution qui produit un URI base64 largement utilisable. Veuillez visiter
data:text/plain;charset=utf-8;base64,4pi44pi54pi64pi74pi84pi+4pi/
pour voir une démonstration (copiez l'URI de données, ouvrez un nouvel onglet, collez l'URI de données dans la barre d'adresse, puis appuyez sur Entrée pour aller à la page). Malgré le fait que cet URI soit encodé en base64, le navigateur est toujours capable de reconnaître les points de code élevés et de les décoder correctement. Le codeur minifié + décodeur est de 1058 octets (+ Gzip → 589 octets)Vous trouverez ci-dessous le code source utilisé pour le générer.
Ensuite, pour décoder les données base64, HTTP récupère les données sous forme d'URI de données ou utilise la fonction ci-dessous.
L'avantage d'être plus standard est que cet encodeur et ce décodeur sont plus largement applicables car ils peuvent être utilisés comme une URL valide qui s'affiche correctement. Observer.
En plus d'être très standardisés, les extraits de code ci-dessus sont également très rapides. Au lieu d'une chaîne de succession indirecte où les données doivent être converties plusieurs fois entre différentes formes (comme dans la réponse de Riccardo Galli), l'extrait de code ci-dessus est aussi direct que possible. Il utilise un seul
String.prototype.replace
appel rapide simple pour traiter les données lors du codage, et un seul pour décoder les données lors du décodage. Un autre avantage est que (en particulier pour les grosses chaînes),String.prototype.replace
permet au navigateur de gérer automatiquement la gestion de la mémoire sous-jacente du redimensionnement de la chaîne, ce qui améliore considérablement les performances, en particulier dans les navigateurs à feuilles persistantes comme Chrome et Firefox qui optimisent fortementString.prototype.replace
. Enfin, la cerise sur le gâteau est que pour les utilisateurs du script latin exclūsīvō, les chaînes qui ne contiennent aucun point de code au-dessus de 0x7f sont très rapides à traiter car la chaîne reste inchangée par l'algorithme de remplacement.J'ai créé un référentiel github pour cette solution à l' adresse https://github.com/anonyco/BestBase64EncoderDecoder/
la source
Les petites corrections, unescape et escape sont obsolètes, donc:
la source
encodeURIComponent
c'est l'inverse dedecodeURIComponent
, c'est-à-dire qu'il annulera simplement la conversion. Voir stackoverflow.com/a/31412163/1534459 pour une bonne explication de ce qui se passe avecescape
etunescape
.encodeURIComponent
est utilisé, est de gérer correctement (toute la gamme de) chaînes Unicode. Donc par exemplewindow.btoa(decodeURIComponent(encodeURIComponent('€')))
donneError: String contains an invalid character
parce que c'est le même quewindow.btoa('€')
etbtoa
ne peut pas encoder€
.Voici un code à l'épreuve du temps pour les navigateurs qui peuvent manquer
escape/unescape()
. Notez que IE 9 et les versions antérieures ne prennent pas en chargeatob/btoa()
, vous devrez donc utiliser des fonctions base64 personnalisées pour eux.Un exemple plus complet d'encodage et de décodage UTF-8 peut être trouvé ici: http://jsfiddle.net/47zwb41o/
la source
y compris la solution ci-dessus si le problème persiste, essayez comme ci-dessous, considérez le cas où l'échappement n'est pas pris en charge pour TS.
pour csv_content, vous pouvez essayer comme ci-dessous.
la source