Wie konvertiere ich eine Datei in Base64 in JavaScript?

186

Jetzt erhalte ich das Dateiobjekt in dieser Zeile:

file = document.querySelector('#files > input[type="file"]').files[0]

Ich muss diese Datei über json in Base 64 senden. Was kann ich tun, um sie in einen Base64-String zu konvertieren?

Vassily
quelle

Antworten:

118

Moderner ES6-Weg (asynchron / warten)

const toBase64 = file => new Promise((resolve, reject) => {
    const reader = new FileReader();
    reader.readAsDataURL(file);
    reader.onload = () => resolve(reader.result);
    reader.onerror = error => reject(error);
});

async function Main() {
   const file = document.querySelector('#myfile').files[0];
   console.log(await toBase64(file));
}

Main();

UPD:

Wenn Sie Fehler abfangen möchten

async function Main() {
   const file = document.querySelector('#myfile').files[0];
   const result = await toBase64(file).catch(e => Error(e));
   if(result instanceof Error) {
      console.log('Error: ', result.message);
      return;
   }
   //...
}
Дмитрий Васильев
quelle
Dieser Code ist falsch. Wenn Sie awaiteine Funktion haben, die ein abgelehntes Versprechen zurückgibt, wird vom Aufruf kein Fehler zurückgegeben. es wird geworfen und du musst es fangen.
Dancrumb
1
Tolles Beispiel für die Verwendung der asynchronen Funktionen und Versprechen
Thiago Frias
291

Probieren Sie die Lösung mit der FileReader Klasse aus :

function getBase64(file) {
   var reader = new FileReader();
   reader.readAsDataURL(file);
   reader.onload = function () {
     console.log(reader.result);
   };
   reader.onerror = function (error) {
     console.log('Error: ', error);
   };
}

var file = document.querySelector('#files > input[type="file"]').files[0];
getBase64(file); // prints the base64 string

Beachten Sie, dass dies .files[0]ein FileTyp ist, der eine Unterklasse von ist Blob. Somit kann es mit verwendet werden FileReader.
Siehe die vollständige Arbeits Beispiel .

Dmitri Pavlutin
quelle
2
Lesen Sie mehr über die FileReader-API: developer.mozilla.org/en-US/docs/Web/API/FileReader und Browserunterstützung: caniuse.com/#feat=filereader
Lukas Liesis
7
Ich habe versucht, return reader.resultdie getBase64()Funktion zu verwenden (anstatt sie zu verwenden console.log(reader.result)), weil ich die base64 als Variable erfassen möchte (und sie dann an Google Apps Script senden möchte). Ich habe die Funktion mit: aufgerufen var my_file_as_base64 = getBase64(file)und dann versucht, auf Konsole zu drucken console.log(my_file_as_base64 )und habe gerade bekommen undefined. Wie kann ich die base64 einer Variablen richtig zuweisen?
user1063287
1
Ich habe aus dem obigen Kommentar eine Frage gemacht, wenn jemand antworten kann. stackoverflow.com/questions/47195119/…
user1063287
Ich muss diese Base64-Datei im Browser mit demselben Dateinamen öffnen. Ich öffne sie mit window.open (URL, '_blank'), was gut funktioniert. Wie kann ich dem einen Dateinamen geben? Bitte helfen Sie.
Munish Sharma
Vielen Dank! Ich denke, das wird auf developer.mozilla.org/en-US/docs/Web/API/FileReader/…
johey
123

Wenn Sie nach einer vielversprechenden Lösung suchen, ist dies der Code von @ Dmitri, der dafür angepasst ist:

function getBase64(file) {
  return new Promise((resolve, reject) => {
    const reader = new FileReader();
    reader.readAsDataURL(file);
    reader.onload = () => resolve(reader.result);
    reader.onerror = error => reject(error);
  });
}

var file = document.querySelector('#files > input[type="file"]').files[0];
getBase64(file).then(
  data => console.log(data)
);
joshua.paling
quelle
Ich muss diese Base64-Datei im Browser mit demselben Dateinamen öffnen. Ich öffne sie mit window.open (URL, '_blank'), was gut funktioniert. Wie kann ich dem einen Dateinamen geben? Bitte helfen Sie.
Munish Sharma
42

Aufbauend auf den Antworten von Dmitri Pavlutin und joshua.paling ist hier eine erweiterte Version, die den base64-Inhalt extrahiert (die Metadaten am Anfang entfernt) und außerdem sicherstellt, dass das Auffüllen korrekt erfolgt .

function getBase64(file) {
  return new Promise((resolve, reject) => {
    const reader = new FileReader();
    reader.readAsDataURL(file);
    reader.onload = () => {
      let encoded = reader.result.toString().replace(/^data:(.*,)?/, '');
      if ((encoded.length % 4) > 0) {
        encoded += '='.repeat(4 - (encoded.length % 4));
      }
      resolve(encoded);
    };
    reader.onerror = error => reject(error);
  });
}
Arnaud P.
quelle
2
Chrome 69, das erste Ersetzen dient zum Abfangen einer leeren Datei, das zweite Ersetzen fehlt comma - encoded = reader.result.replace ("data:", "") .replace (/^.*; base64, /, "");
user3333134
Mein Wort, ich habe dieses Koma wirklich vermisst. Was unglaublich ist, ist, dass es mein Backend überhaupt nicht zu stören schien, ich konnte immer noch erfolgreich Excel-Dateien hochladen o_O. Ich habe den regulären Ausdruck korrigiert, um auch Ihren Anwendungsfall für leere Dateien zu berücksichtigen. Vielen Dank.
Arnaud P
2
Ich habe eine noch einfachere Version : resolve(reader.result.replace(/^.*,/, ''));. Da das Koma ,außerhalb des Base64-Alphabets liegt, können wir alles entfernen, was bis einschließlich des Komas auftritt. stackoverflow.com/a/13195218/1935128
Johnride
Ok, danke für das Heads-up, obwohl es laut dem regulären Ausdruck, den ich hier geschrieben habe (ich müsste noch einmal experimentieren, um sicherzugehen), möglicherweise nur data:ohne Komma gibt, also werde ich den ersten Teil so lassen, wie er ist. Ich habe die Antwort entsprechend aktualisiert.
Arnaud P
1
@ArnaudP Typoskriptfehler: Die Eigenschaft 'replace' ist für den Typ 'string | nicht vorhanden ArrayBuffer '.
Romel Gomez
12

Die JavaScript- Funktion btoa () kann verwendet werden, um Daten in eine Base64-codierte Zeichenfolge zu konvertieren

Pranav Maniar
quelle
6
btoa funktioniert nur mit string. Wie benutzt man es mit Datei?
Vassily
10
Sie müssen zuerst die Datei lesen und dann an diese Funktion übergeben. So etwas wie jsfiddle.net/eliseosoto/JHQnk
Pranav Maniar
1
@PranavManiar Deine Geige funktioniert nicht mehr. Können Sie den Link aktualisieren?
Dan
5

Hier sind einige Funktionen, die ich geschrieben habe, um eine Datei in einem JSON-Format zu erhalten, die leicht weitergegeben werden kann:

    //takes an array of JavaScript File objects
    function getFiles(files) {
        return Promise.all(files.map(file => getFile(file)));
    }

    //take a single JavaScript File object
    function getFile(file) {
        var reader = new FileReader();
        return new Promise((resolve, reject) => {
            reader.onerror = () => { reader.abort(); reject(new Error("Error parsing file"));}
            reader.onload = function () {

                //This will result in an array that will be recognized by C#.NET WebApi as a byte[]
                let bytes = Array.from(new Uint8Array(this.result));

                //if you want the base64encoded file you would use the below line:
                let base64StringFile = btoa(bytes.map((item) => String.fromCharCode(item)).join(""));

                //Resolve the promise with your custom file structure
                resolve({ 
                    bytes: bytes,
                    base64StringFile: base64StringFile,
                    fileName: file.name, 
                    fileType: file.type
                });
            }
            reader.readAsArrayBuffer(file);
        });
    }

    //using the functions with your file:

    file = document.querySelector('#files > input[type="file"]').files[0]
    getFile(file).then((customJsonFile) => {
         //customJsonFile is your newly constructed file.
         console.log(customJsonFile);
    });

    //if you are in an environment where async/await is supported

    files = document.querySelector('#files > input[type="file"]').files
    let customJsonFiles = await getFiles(files);
    //customJsonFiles is an array of your custom files
    console.log(customJsonFiles);
tkd_aj
quelle
1
Versprich es allen, basierend auf einer array.map funktioniert großartig! Zumindest für mich.
Davidwillianx
0
onInputChange(evt) {
    var tgt = evt.target || window.event.srcElement,
    files = tgt.files;
    if (FileReader && files && files.length) {
        var fr = new FileReader();
        fr.onload = function () {
            var base64 = fr.result;
            debugger;
        }
        fr.readAsDataURL(files[0]);
    }
}
user2120895
quelle