Tengo un sitio local que usa Javascript para buscar archivos en mi máquina. Esta no es una pregunta de NodeJS. He estado leyendo archivos binarios en mi sistema de archivos local y convirtiéndolos a base64. El problema que tengo es cuando hay caracteres no imprimibles. El resultado que obtengo de javascript es diferente a la herramienta de línea de comando base64 en Linux.
Se generó un archivo de ejemplo, que podemos usar para esta pregunta, con head -c 8 /dev/random > random -- es solo una tontería binaria escrita en un archivo. En este ejemplo arrojó lo siguiente:
$ base64 random Tg8j3hAv/u4=Si quieres jugar en casa, puedes ejecutar esto para generar el mismo archivo:
echo -n 'Tg8j3hAv/u4=' | base64 -d > randomSin embargo, cuando intento leer ese archivo en Javascript y convertirlo a base64, obtengo un resultado diferente:
Tg8j77+9EC/vv73vv70=Se ve un poco similar, pero con algunos otros personajes allí.
Así es como lo conseguí:
function readTextFile(file) { let fileContents; var rawFile = new XMLHttpRequest(); rawFile.open("GET", file, false); rawFile.onreadystatechange = function () { if(rawFile.readyState === 4) { if(rawFile.status === 200 || rawFile.status == 0) { fileContents = rawFile.responseText; } } } rawFile.send(null); return fileContents; } var fileContents = readTextFile("file:///Users/henrytk/tmp/stuff/random"); console.log(btoa(unescape(encodeURIComponent(fileContents)))); // I also tried console.log(Base64.encode(fileContents)); // from http://www.webtoolkit.info/javascript_base64.html#.YVW4WaDTW_w // but I got the same result¿Cómo está pasando esto? ¿Tiene algo que ver con la forma en que estoy leyendo el archivo? Quiero poder leer ese archivo sincrónicamente de una manera que se pueda ejecutar localmente , sin NodeJS, sin bibliotecas de terceros sofisticadas, si es posible.
Creo que este es el problema:
fileContents = rawFile.responseText
Esto leerá su archivo como una cadena JavaScript, y no todos los binarios son puntos de código de caracteres JavaScript válidos.
Recomendaré usar fetch para obtener un blob, ya que ese es el método que mejor conozco:
async function readTextFileAsBlob(file) { const response = await fetch( file ); const blob = await response.blob(); return blob; } Luego, convierta el blob a base64 usando FileReader del navegador.
(¿Tal vez eso coincida con la herramienta de Linux?)
const blobToBase64DataURL = blob => new Promise( resolvePromise => { const reader = new FileReader(); reader.onload = () => resolvePromise( reader.result ); reader.readAsDataURL( blob ); } );En su ejemplo, usaría estas funciones así:
readTextFileAsBlob( "file:///Users/henrytk/tmp/stuff/random" ).then( async blob => { const base64URL = await blobToBase64DataURL( blob ); console.log( base64URL ); } ); Esto le dará una URL como data://... . Deberá separar la parte de la URL, pero si todo va bien, el último bit debería ser la información base64 correcta. (Ojalá).