O código Base64 útil começa decidindo qual é realmente a entrada. Uma string JavaScript precisa de uma codificação de caracteres; um arquivo já possui bytes; um valor JSON precisa de serialização primeiro. Manter essas etapas visíveis facilita a depuração e evita codificação dupla acidental.
Codifique um pequeno valor JSON
Serialize o valor exatamente uma vez, codifique essa string como UTF-8 e, em seguida, codifique os bytes como Base64. Este exemplo inclui um campo não ASCII para capturar implementações que funcionam apenas com inglês. Destina-se a pequenas cargas úteis; a sequência de bytes temporária aumenta o uso de memória.
const value = { message: '你好', count: 3 };
const text = JSON.stringify(value);
let binary = '';
for (const byte of new TextEncoder().encode(text)) {
binary += String.fromCharCode(byte);
}
const encoded = btoa(binary);
const bytes = Uint8Array.from(atob(encoded), c => c.charCodeAt(0));
const json = new TextDecoder('utf-8', { fatal: true }).decode(bytes);
console.log(JSON.parse(json).message); // 你好
Uma decodificação Base64 bem-sucedida não garante JSON válido. Trate a decodificação UTF-8 e JSON.parse como pontos de falha separados. Quando o conteúdo decodificado já é uma string contendo JSON, serializá-lo novamente adiciona aspas e escapes; isso altera a carga útil.
Ler um arquivo selecionado como bytes
Para um navegador File, usar arrayBuffer() quando você precisar dos bytes subjacentes. Não use file.text() para uma imagem, arquivo ou arquivo criptografado: sequências de caracteres inválidas podem se tornar caracteres de substituição. Se o seu destino precisar de dados URI, FileReader.readAsDataURL() fornece o wrapper, bem como os dados Base64.
// file is a File selected by the user.
const bytes = new Uint8Array(await file.arrayBuffer());
console.log(bytes.byteLength); // original file size in bytes
// Pass bytes to a byte-oriented encoder, not TextEncoder.
Verificações de ida e volta que detectam erros reais
Compare os bytes decodificados com a matriz de bytes original. A comparação de capturas de tela ou nomes de arquivos não detecta um byte alterado. Inclui entrada vazia, todos os valores de bytes de 0 a 255, texto chinês, emoji e uma carga útil cujo comprimento deixa um ou dois bytes no grupo final. Para um lote de arquivos, preserve o nome, o tamanho e o resultado de cada arquivo de forma independente para que um erro não possa substituir outra saída bem-sucedida.
Mantenha as conversões locais, a menos que seu fluxo de trabalho chame intencionalmente um API. Uma solicitação de rede contendo a saída codificada ainda envia os dados subjacentes de forma reversível. Para o comportamento da string de bytes e a limitação Unicode da função do navegador, consulte MDN: btoa().