Estou usando a window.atob()
função Javascript para decodificar uma string codificada em base64 (especificamente o conteúdo codificado em base64 da API do GitHub). O problema é que estou recebendo caracteres codificados em ASCII de volta (como em â¢
vez de ™
). Como posso controlar adequadamente o fluxo de entrada codificado em base64 para que seja decodificado como utf-8?
javascript
encoding
utf-8
brandonscript
fonte
fonte
atob
Respostas:
Há um ótimo artigo sobre os documentos MDN da Mozilla que descreve exatamente esse problema:
Uma observação sobre soluções anteriores: o artigo MDN originalmente sugeriu usar
unescape
eescape
resolver oCharacter Out Of Range
problema de exceção, mas eles foram descontinuados. Algumas outras respostas aqui sugeriram contornar isso comdecodeURIComponent
eencodeURIComponent
, isso se provou não confiável e imprevisível. A atualização mais recente para esta resposta usa funções JavaScript modernas para melhorar a velocidade e modernizar o código.Se você está tentando economizar tempo, também pode considerar o uso de uma biblioteca:
Codificação UTF8 ⇢ base64
Decodificando base64 ⇢ UTF8
A solução pré-2018 (funcional e, embora provavelmente com melhor suporte para navegadores mais antigos, não está atualizada)
Aqui está a recomendação atual, direto do MDN, com alguma compatibilidade TypeScript adicional via @ MA-Maddin:
A solução original (obsoleta)
Este usado
escape
eunescape
(que agora estão obsoletos, embora ainda funcione em todos os navegadores modernos):E uma última coisa: encontrei esse problema pela primeira vez ao chamar a API do GitHub. Para fazer isso funcionar no Safari (móvel) corretamente, eu realmente tive que remover todo o espaço em branco da fonte base64 antes mesmo de decodificar a fonte. Se isso ainda é relevante ou não em 2017, não sei:
fonte
b64DecodeUnicode('4pyTIMOgIGxhIG1vZGU=');
agora a saída correta "✓ à la mode"decodeURIComponent(atob('4pyTIMOgIGxhIG1vZGU=').split('').map(x => '%' + x.charCodeAt(0).toString(16)).join(''))
Não o código de melhor desempenho, mas é o que é.return String.fromCharCode(parseInt(p1, 16));
para ter compatibilidade com TypeScript.As coisas mudam. Os métodos de escape / unescape foram descontinuados.
Você pode codificar a string em URI antes de codificá-la em Base64. Observe que isso não produz UTF8 codificado em Base64, mas sim dados codificados em URL codificados em Base64. Ambos os lados devem concordar com a mesma codificação.
Veja o exemplo de trabalho aqui: http://codepen.io/anon/pen/PZgbPW
Para o problema de OP, uma biblioteca de terceiros, como js-base64, deve resolver o problema.
fonte
Se você prefere tratar strings como bytes, você pode usar as seguintes funções
fonte
Aqui está a solução atualizada de 2018, conforme descrito em Recursos de desenvolvimento do Mozilla
PARA CODIFICAR DE UNICODE PARA B64
PARA DECODIFICAR DE B64 PARA UNICODE
fonte
O artigo completo que funciona para mim: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Base64_encoding_and_decoding
A parte onde codificamos de Unicode / UTF-8 é
Este é um dos métodos mais utilizados atualmente.
fonte
Eu diria que alguém pode querer uma solução que produza um URI base64 amplamente utilizável. Visite
data:text/plain;charset=utf-8;base64,4pi44pi54pi64pi74pi84pi+4pi/
para ver uma demonstração (copie o uri de dados, abra uma nova guia, cole o URI de dados na barra de endereço e pressione Enter para ir para a página). Apesar do fato de que este URI é codificado em base64, o navegador ainda é capaz de reconhecer os pontos de código elevados e decodificá-los corretamente. O codificador + decodificador minimizado tem 1058 bytes (+ Gzip → 589 bytes)Abaixo está o código-fonte usado para gerá-lo.
Em seguida, para decodificar os dados base64, o HTTP obtém os dados como um URI de dados ou use a função abaixo.
A vantagem de ser mais padrão é que esse codificador e esse decodificador são mais amplamente aplicáveis, pois podem ser usados como um URL válido que é exibido corretamente. Observar.
Além de serem muito padronizados, os trechos de código acima também são muito rápidos. Em vez de uma cadeia indireta de sucessão em que os dados precisam ser convertidos várias vezes entre várias formas (como na resposta de Riccardo Galli), o trecho de código acima é o mais direto possível. Ele usa apenas uma
String.prototype.replace
chamada rápida simples para processar os dados durante a codificação e apenas uma para decodificar os dados durante a decodificação. Outra vantagem é que (especialmente para strings grandes),String.prototype.replace
permite que o navegador lide automaticamente com o gerenciamento de memória subjacente de redimensionamento da string, levando a um aumento significativo de desempenho, especialmente em navegadores perenes como Chrome e Firefox que otimizam fortementeString.prototype.replace
. Finalmente, a cereja do bolo é que, para os usuários exclūsīvō do script latino, as strings que não contêm nenhum ponto de código acima de 0x7f são extremamente rápidas de processar porque a string permanece inalterada pelo algoritmo de substituição.Eu criei um repositório github para esta solução em https://github.com/anonyco/BestBase64EncoderDecoder/
fonte
Correção pequena, unescape e escape são descontinuados, então:
fonte
encodeURIComponent
é o inverso dedecodeURIComponent
, ou seja, só vai desfazer a conversão. Consulte stackoverflow.com/a/31412163/1534459 para uma ótima explicação do que está acontecendo comescape
eunescape
.encodeURIComponent
é usado é para lidar corretamente (com toda a gama de) strings Unicode. Então, por exemplo,window.btoa(decodeURIComponent(encodeURIComponent('€')))
dáError: String contains an invalid character
porque é o mesmo quewindow.btoa('€')
ebtoa
não pode codificar€
.Aqui está um código à prova de futuro para navegadores que podem faltar
escape/unescape()
. Observe que o IE 9 e anteriores não são compatíveisatob/btoa()
, portanto, você precisará usar funções base64 personalizadas para eles.Um exemplo mais abrangente de codificação e decodificação UTF-8 pode ser encontrado aqui: http://jsfiddle.net/47zwb41o/
fonte
incluindo a solução acima, se ainda estiver enfrentando problemas, tente como abaixo. Considere o caso em que escape não é compatível com TS.
para csv_content você pode tentar como abaixo.
fonte