Używam window.atob()
funkcji JavaScript do dekodowania ciągu zakodowanego w formacie base64 (w szczególności treści zakodowanej w formacie base64 z interfejsu API GitHub). Problem polega na tym, że otrzymuję z powrotem znaki zakodowane w ASCII (jak â¢
zamiast ™
). Jak mogę poprawnie obsłużyć przychodzący strumień zakodowany w base64, aby został zdekodowany jako utf-8?
javascript
encoding
utf-8
brandonscript
źródło
źródło
atob
Odpowiedzi:
Jest świetny artykuł na temat dokumentacji MDN Mozilli, który opisuje dokładnie ten problem:
Uwaga na temat poprzednich rozwiązań: artykuł MDN pierwotnie sugerował użycie
unescape
iescape
rozwiązanieCharacter Out Of Range
problemu wyjątku, ale od tego czasu są one przestarzałe. Niektóre inne odpowiedzi tutaj sugerują pracy wokół to zedecodeURIComponent
iencodeURIComponent
ta okazała się zawodna i nieprzewidywalne. Najnowsza aktualizacja tej odpowiedzi wykorzystuje nowoczesne funkcje JavaScript w celu zwiększenia szybkości i modernizacji kodu.Jeśli chcesz zaoszczędzić trochę czasu, możesz również rozważyć skorzystanie z biblioteki:
Kodowanie UTF8 ⇢ base64
Dekodowanie base64 ⇢ UTF8
Rozwiązanie sprzed 2018 r. (Funkcjonalne i prawdopodobnie lepsze wsparcie dla starszych przeglądarek, nieaktualne)
Oto aktualne zalecenie, bezpośrednio z MDN, z dodatkową kompatybilnością z TypeScript przez @ MA-Maddin:
Oryginalne rozwiązanie (przestarzałe)
To używane
escape
iunescape
(które są teraz przestarzałe, chociaż nadal działa we wszystkich nowoczesnych przeglądarkach):I ostatnia rzecz: po raz pierwszy napotkałem ten problem podczas wywoływania interfejsu API GitHub. Aby to działało poprawnie w (mobilnym) Safari, musiałem usunąć całą białą przestrzeń ze źródła base64, zanim mogłem nawet zdekodować źródło. Czy jest to nadal aktualne w 2017 roku, nie wiem:
źródło
b64DecodeUnicode('4pyTIMOgIGxhIG1vZGU=');
teraz poprawnie wyświetla "✓ à la mode"decodeURIComponent(atob('4pyTIMOgIGxhIG1vZGU=').split('').map(x => '%' + x.charCodeAt(0).toString(16)).join(''))
nie najbardziej wydajny kod, ale taki właśnie jest.return String.fromCharCode(parseInt(p1, 16));
mieć zgodność z TypeScript.Rzeczy się zmieniają. Metody ucieczki / unescape zostały wycofane.
Możesz zakodować ciąg znaków URI przed zakodowaniem go w formacie Base64. Zauważ, że to nie tworzy danych zakodowanych w formacie Base64 UTF8, ale raczej dane zakodowane w formacie Base64 zakodowane w adresie URL. Obie strony muszą zgodzić się na to samo kodowanie.
Zobacz działający przykład tutaj: http://codepen.io/anon/pen/PZgbPW
W przypadku problemu OP, biblioteka innej firmy, taka jak js-base64, powinna rozwiązać problem.
źródło
Jeśli bardziej interesuje Cię traktowanie łańcuchów jako bajtów, możesz użyć następujących funkcji
źródło
Oto zaktualizowane rozwiązanie 2018, opisane w zasobach programistycznych Mozilli
ABY KODOWAĆ Z UNICODE DO B64
ODKODOWAĆ OD B64 DO UNICODE
źródło
Cały artykuł, który działa dla mnie: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Base64_encoding_and_decoding
Część, w której kodujemy z Unicode / UTF-8, to
Jest to obecnie jedna z najczęściej stosowanych metod.
źródło
Przypuszczam, że można chcieć rozwiązania, które tworzy powszechnie używany identyfikator URI base64. Odwiedź witrynę,
data:text/plain;charset=utf-8;base64,4pi44pi54pi64pi74pi84pi+4pi/
aby zobaczyć demonstrację (skopiuj uri danych, otwórz nową kartę, wklej identyfikator URI danych w pasku adresu, a następnie naciśnij klawisz Enter, aby przejść do strony). Pomimo faktu, że ten identyfikator URI jest zakodowany w base64, przeglądarka nadal jest w stanie rozpoznać wysokie punkty kodowe i poprawnie je zdekodować. Zminimalizowany koder + dekoder ma 1058 bajtów (+ Gzip → 589 bajtów)Poniżej znajduje się kod źródłowy użyty do jego wygenerowania.
Następnie, aby zdekodować dane base64, pobierz dane HTTP jako identyfikator URI danych lub użyj poniższej funkcji.
Zaletą bycia bardziej standardowym jest to, że ten koder i ten dekoder mają szersze zastosowanie, ponieważ mogą być używane jako prawidłowy adres URL, który wyświetla się poprawnie. Przestrzegać.
Oprócz tego, że są bardzo znormalizowane, powyższe fragmenty kodu są również bardzo szybkie. Zamiast pośredniego łańcucha sukcesji, w którym dane muszą być wielokrotnie konwertowane między różnymi formami (tak jak w odpowiedzi Riccardo Galli), powyższy fragment kodu jest tak bezpośredni, jak to wykonalne. Używa tylko jednego prostego szybkiego
String.prototype.replace
wywołania do przetwarzania danych podczas kodowania i tylko jednego do dekodowania danych podczas dekodowania. Kolejną zaletą jest to, że (szczególnie w przypadku dużych ciągów znaków)String.prototype.replace
pozwala przeglądarce automatycznie obsługiwać podstawowe zarządzanie pamięcią polegającą na zmianie rozmiaru ciągu, co prowadzi do znacznego wzrostu wydajności, szczególnie w wiecznie zielonych przeglądarkach, takich jak Chrome i Firefox, które mocno optymalizująString.prototype.replace
. Wreszcie wisienką na torcie jest to, że dla użytkowników skryptów łacińskich exclūsīvō, ciągi znaków, które nie zawierają żadnych punktów kodowych powyżej 0x7f, są wyjątkowo szybkie w przetwarzaniu, ponieważ ciąg pozostaje niezmieniony przez algorytm zastępujący.Utworzyłem repozytorium github dla tego rozwiązania pod adresem https://github.com/anonyco/BestBase64EncoderDecoder/
źródło
Drobne poprawki, unescape i escape są przestarzałe, więc:
źródło
encodeURIComponent
jest odwrotnościądecodeURIComponent
, tj. Po prostu cofnie konwersję. Zobacz stackoverflow.com/a/31412163/1534459, aby uzyskać świetne wyjaśnienie, co się dzieje zescape
iunescape
.encodeURIComponent
jest używany, jest poprawna obsługa (całego zakresu) ciągów znaków Unicode. Czyli np.window.btoa(decodeURIComponent(encodeURIComponent('€')))
DajeError: String contains an invalid character
bo to to samo cowindow.btoa('€')
ibtoa
nie potrafi zakodować€
.Oto kilka przyszłych kodów dla przeglądarek, których może brakować
escape/unescape()
. Pamiętaj, że IE 9 i starsze nie obsługująatob/btoa()
, więc musisz użyć dla nich niestandardowych funkcji base64.Bardziej obszerny przykład kodowania i dekodowania UTF-8 można znaleźć tutaj: http://jsfiddle.net/47zwb41o/
źródło
w tym powyższe rozwiązanie, jeśli nadal napotykasz problem, spróbuj jak poniżej, Rozważ przypadek, w którym ucieczka nie jest obsługiwana dla TS.
dla csv_content możesz spróbować jak poniżej.
źródło