Das Auswählen von Dateien auf dem lokalen Gerät des Nutzers und die Interaktion mit ihnen ist eine der am häufigsten verwendeten Funktionen im Web. Nutzer können damit Dateien auswählen und auf einen Server hochladen, z. B. beim Teilen von Fotos oder Einreichen von Steuerunterlagen. Außerdem können Websites die Dateien lesen und bearbeiten, ohne die Daten über das Netzwerk übertragen zu müssen. Auf dieser Seite wird beschrieben, wie Sie mit JavaScript mit Dateien interagieren.
Die moderne File System Access API
Die File System Access API bietet eine Möglichkeit, Dateien und Verzeichnisse auf dem lokalen System des Nutzers zu lesen und in sie zu schreiben. Sie ist in den meisten Chromium-basierten Browsern wie Chrome und Edge verfügbar. Weitere Informationen finden Sie unter File System Access API.
Da die File System Access API nicht mit allen Browsern kompatibel ist, empfehlen wir die Verwendung von browser-fs-access, einer Hilfsbibliothek, die die neue API verwendet, wenn sie verfügbar ist, und auf ältere Ansätze zurückgreift, wenn sie nicht verfügbar ist.
Mit Dateien arbeiten – die klassische Methode
In diesem Leitfaden erfahren Sie, wie Sie mit älteren JavaScript-Methoden mit Dateien interagieren.
Dateien auswählen
Es gibt zwei Hauptmethoden zum Auswählen von Dateien: das HTML-Eingabeelementund eine Drag-and-drop-Zone.
HTML-Eingabeelement
Die einfachste Möglichkeit für Nutzer, Dateien auszuwählen, ist das
<input type="file">
Element, das in allen wichtigen Browsern unterstützt wird. Wenn darauf geklickt wird, kann ein Nutzer
eine oder mehrere Dateien auswählen, wenn das
multiple
Attribut enthalten ist. Dazu wird die integrierte Dateiauswahl
UI des Betriebssystems verwendet. Wenn der Nutzer die Auswahl einer oder mehrerer Dateien abgeschlossen hat, wird das Ereignis change des Elements ausgelöst. Sie können über event.target.files auf die Liste der Dateien zugreifen. Dabei
handelt es sich um ein FileList-Objekt.
Jedes Element in der FileList ist ein File-Objekt.
<!-- The `multiple` attribute lets users select multiple files. -->
<input type="file" id="file-selector" multiple>
<script>
const fileSelector = document.getElementById('file-selector');
fileSelector.addEventListener('change', (event) => {
const fileList = event.target.files;
console.log(fileList);
});
</script>
Im folgenden Beispiel kann ein Nutzer mehrere Dateien über die integrierte Dateiauswahl-UI des Betriebssystems auswählen. Jede ausgewählte Datei wird dann in der Console protokolliert.
Die Dateitypen einschränken, die Nutzer auswählen können
In einigen Fällen möchten Sie möglicherweise die Dateitypen einschränken, die Nutzer auswählen können. Eine Bildbearbeitungs-App sollte beispielsweise nur Bilder und keine Textdateien akzeptieren. Wenn Sie
Einschränkungen für Dateitypen festlegen möchten, fügen Sie dem Eingabeelement ein
accept
Attribut hinzu, um anzugeben, welche Dateitypen akzeptiert werden:
<input type="file" id="file-selector" accept=".jpg, .jpeg, .png">
Benutzerdefiniertes Drag-and-drop
In einigen Browsern ist das <input type="file"> Element auch ein Ablageziel,
sodass Nutzer Dateien per Drag-and-drop in Ihre App ziehen können. Dieses Ablageziel
ist jedoch klein und kann schwer zu verwenden sein. Nachdem Sie die Kernfunktionen mit
einem <input type="file"> Element bereitgestellt haben, können Sie stattdessen eine große, benutzerdefinierte Drag-and-drop
Oberfläche anbieten.
Ablagezone auswählen
Die Ablageoberfläche hängt vom Design Ihrer Anwendung ab. Möglicherweise soll nur ein Teil des Fensters als Ablageoberfläche dienen, Sie können aber auch das gesamte Fenster verwenden.
Mit der Bildkomprimierungs-App Squoosh können Nutzer ein Bild an eine beliebige Stelle im
Fenster ziehen und auf Bild auswählen klicken, um das <input type="file">
Element aufzurufen. Was auch immer Sie als Ablagezone auswählen, machen Sie dem Nutzer deutlich, dass er Dateien auf diese Oberfläche ziehen kann.
Ablagezone definieren
Wenn Sie ein Element als Drag-and-drop-Zone aktivieren möchten, erstellen Sie Listener für
zwei Ereignisse: dragover
und drop.
Das Ereignis dragover aktualisiert die Browser-UI, um visuell anzugeben, dass bei der Drag-and-drop-Aktion eine Kopie der Datei erstellt wird. Das Ereignis drop wird ausgelöst, nachdem der Nutzer die Dateien auf die Oberfläche gezogen hat. Wie beim Eingabeelement können Sie über event.dataTransfer.files auf die Liste der Dateien zugreifen. Dabei handelt es sich um ein
FileList-Objekt. Jedes
Element in der FileList ist ein File-Objekt.
const dropArea = document.getElementById('drop-area');
dropArea.addEventListener('dragover', (event) => {
event.stopPropagation();
event.preventDefault();
// Style the drag-and-drop as a "copy file" operation.
event.dataTransfer.dropEffect = 'copy';
});
dropArea.addEventListener('drop', (event) => {
event.stopPropagation();
event.preventDefault();
const fileList = event.dataTransfer.files;
console.log(fileList);
});
event.stopPropagation()
und event.preventDefault()
verhindern das Standardverhalten des Browsers und ermöglichen stattdessen die Ausführung Ihres Codes. Andernfalls würde der Browser von Ihrer Seite weg navigieren und die Dateien öffnen, die der Nutzer in das Browserfenster gezogen hat.
Eine Live-Demo finden Sie unter Benutzerdefiniertes Drag-and-drop.
Was ist mit Verzeichnissen?
Leider gibt es keine gute Möglichkeit, mit JavaScript auf ein Verzeichnis zuzugreifen.
Das webkitdirectory
Attribut im Element <input type="file"> kann dem Nutzer ein Verzeichnis
oder mehrere Verzeichnisse auswählen. Es wird in den meisten wichtigen Browsern unterstützt
, mit Ausnahme von Firefox für Android und Safari unter iOS.
Wenn Drag-and-drop aktiviert ist, versucht ein Nutzer möglicherweise, ein Verzeichnis in die Ablagezone zu ziehen. Wenn das Ereignis „drop“ ausgelöst wird, enthält es ein File-Objekt für das Verzeichnis, bietet aber keinen Zugriff auf die Dateien im Verzeichnis.
Dateimetadaten lesen
Das File-Objekt enthält Metadaten zur Datei. Die meisten Browser geben den Dateinamen, die Dateigröße und den MIME-Typ an. Je nach Plattform können verschiedene Browser jedoch unterschiedliche oder zusätzliche Informationen liefern.
function getMetadataForFileList(fileList) {
for (const file of fileList) {
// Not supported in Safari for iOS.
const name = file.name ? file.name : 'NOT SUPPORTED';
// Not supported in Firefox for Android or Opera for Android.
const type = file.type ? file.type : 'NOT SUPPORTED';
// Unknown cross-browser support.
const size = file.size ? file.size : 'NOT SUPPORTED';
console.log({file, name, type, size});
}
}
Sie können dies in der input-type-file
Demo in Aktion sehen.
Inhalt einer Datei lesen
Verwenden Sie FileReader, um
den Inhalt eines File-Objekts in den Arbeitsspeicher zu lesen. Sie können FileReader anweisen, eine Datei als Array-Puffer, eine Daten-URL oder Text zu lesen:
function readImage(file) {
// Check if the file is an image.
if (file.type && !file.type.startsWith('image/')) {
console.log('File is not an image.', file.type, file);
return;
}
const reader = new FileReader();
reader.addEventListener('load', (event) => {
img.src = event.target.result;
});
reader.readAsDataURL(file);
}
In diesem Beispiel wird eine vom Nutzer bereitgestellte File gelesen, dann in eine Daten-URL konvertiert und mit dieser Daten-URL das Bild in einem img-Element angezeigt.
Informationen zum Prüfen, ob der Nutzer eine Bilddatei ausgewählt hat, finden Sie in der
read-image-file Demo.
Fortschritt des Lesens einer Datei überwachen
Beim Lesen großer Dateien kann es hilfreich sein, dem Nutzer mit einer UX-Funktion mitzuteilen, wie weit der Lesevorgang fortgeschritten ist. Verwenden Sie dazu das
progress
Ereignis, das von FileReader bereitgestellt wird. Das Ereignis progress hat zwei Eigenschaften: loaded (die gelesene Menge) und total (die zu lesende Menge).
function readFile(file) {
const reader = new FileReader();
reader.addEventListener('load', (event) => {
const result = event.target.result;
// Do something with result
});
reader.addEventListener('progress', (event) => {
if (event.loaded && event.total) {
const percent = (event.loaded / event.total) * 100;
console.log(`Progress: ${Math.round(percent)}`);
}
});
reader.readAsDataURL(file);
}