HTML5 File API – Bildervorschau mit jQuery

HTML5 ist die schöne neue Welt der Webentwicklung und bringt viele neue Features mit sich. Eines der Interessanteren ist hierbei die File API. Auch wenn diese keine bahnbrechenden Neuerungen bringt, steigert Sie richtig eingesetzt die Benutzerfreundlichkeit für den Besucher sowie die Integration des Client-PC’s ungemein. Dieser Artikel soll einen ersten Einstieg vermitteln.

Mit der File API ist es möglich, direkt auf das Dateisystem des Benutzers zuzugreifen. Aber keine Panik, der Zugriff auf das lokale Dateisystem kann nicht ohne Einwilligung des Benutzers geschehen und auch nur auf bestimmte vom Benutzer freigegebene Dateien. So ist es nun z.B. möglich, Dateien für eine Live-Vorschau direkt im Browser anzuzeigen, ohne diese vorher hochladen zu müssen. Ebenso kann man nun Uploads vernünftig im Hintergrund mittels AJAX-Request starten, bevor das gesamte Formular abgeschickt werden muss.

Vorschau eines Bildes anzeigen

Zuerst widmen wir uns der Vorschau eines ausgewählten Bildes für den Upload. Dafür benötigen wir eine kleine HTML Seite mit einem Formular und einem Feld für einen Dateiupload wie diese:

<!DOCTYPE html>
<html>
    <head>
        <title>HTML5 - FileAPI - Vorschau eines Bildes erzeugen</title>
        <script src="https://ajax.googleapis.com/ajax/libs/jquery/1.7.2/jquery.min.js"></script>
    </head>
    <body>
        <form enctype="multipart/form-data">
            <label for="file-upload">Datei(en):</label>
            <input type="file" multiple="multiple" id="file-upload" name="file-upload" />
        </form>
        <div id="preview">
            <!-- Hier erscheinen die Vorschaubilder -->
        </div>
    </body>
</html>

In dieser HTML Datei wird lediglich ein Formular mit einem Feld zur Dateiauswahl ausgegeben, welches wir benötigen, damit wir wissen, welche Bilder der Benutzer hochladen möchte. Um die Browserkompatibilität sicherzustellen habe ich hier bereits ein JavaScript eingebunden. Google ist so freundlich und hostet die jQuery Library für Jedermann zugänglich.

Da die File API eine Erweiterung von JavaScript ist, benötigen wir nun noch ein neues <script>-Tag in welches wir unsere Änderungen einfügen können. Dieses sollte natürlich im <head>-Tag stehen und zu Beginn wie folgt aussehen:

$(function() {
    $('#file-upload').change(function(e) {
    	alert('Neue Datei wurde gewählt');
    });
});

Dieses kleine Script sollte jedem der schon einmal mit jQuery gearbeitet hat ziemlich vertraut vorkommen. Um sicherzustellen, dass zur Laufzeit jegliches HTML geladen ist übergeben wir der „magischen“ $-Methode eine anonyme Funktion welche dann ausgeführt werden soll. In dieser Funktion fügen wir dem zuvor erstellten <input>-Element mit der ID „file-upload“ einen neuen EventListener hinzu, welcher das „onChange“-Event überwacht. Dieses tritt immer dann ein, wenn der Benutzer eine neue Datei für die Vorschau auswählt. Aktuell gibt das Script immer eine Meldung aus, wenn eine neue Datei gewählt wurde. Im Browser sollte das ganze aktuell so aussehen wie auf unserer Beispielseite:

https://www.checkdomain.de/blog/beispiele/html5/file-api/preview/schritt-1.html

Auf Verfügbarkeit der HTML5 File API prüfen

Die 4. Zeile mit der „alert“-Anweisung, welche bereits markiert ist, ersetzen wir nun durch ein paar Prüfungen, welche vorab laufen sollten, so dass das Script wie folgt ausschaut:

$(function() {
    $('#file-upload').change(function(e) {
    	// Prüfen ob die File API vorhanden ist
    	if (this.files !== 'undefined' && typeof FileReader !== 'undefined') {
    		alert('Ihr Browser unterstützt die HTML5 File API');
    	} else {
    		alert('Leider keine HTML5 File API in Ihrem Browser vorhanden.');
    	}
    });
});

https://www.checkdomain.de/blog/beispiele/html5/file-api/preview/schritt-2.html

Mit dieser Prüfung wird zuerst geschaut, ob this.files sowie eine „Klasse“ vom Typ FileReader überhaupt vorhanden sind. Dies ist notwendig, da noch nicht alle Browser. die aktuell eingesetzt werden, über die HTML5 File API verfügen.

Unterstützte Dateitypen filtern

Um fortzufahren ersetzen wir die markierte Zeile wieder, so dass folgendes Script dabei herauskommt:

$(function() {
    $('#file-upload').change(function(e) {
    	// Prüfen ob die File API vorhanden ist
        if (this.files !== 'undefined' && typeof FileReader !== 'undefined') {
            // Schleife über alle gewählten Dateien
            for (var f = 0; f < this.files.length; f++) {
                var file = this.files[f];
                var reader = new FileReader();

                // Prüfen, ob auch wirklich ein Bild gewählt wurde
                if (!/image\/(jpeg|jpg|png|gif)/.test(file.type)) {
                    alert('Dateityp "' + file.type + '" wird nicht unterstützt.');
                    continue;
                }

                // Einlesen der Datei beginnen
                reader.readAsDataURL(file);
            }
        } else {
            alert('Leider keine HTML5 File API in Ihrem Browser vorhanden.');
        }
    });
});

https://www.checkdomain.de/blog/beispiele/html5/file-api/preview/schritt-3.html

Neu hinzugekommen ist hier die markierte „for“-Schleife, welche einmal pro ausgewählte Datei durchlaufen wird. In der „for“-Schleife wird jede einzelne ausgewählte Datei in eine neue Variable namens „file“ geschrieben, sowie eine neue Instanz der „FileReader“-Klasse erzeugt.

Auch hier benötigen wir wieder Prüfungen, damit nicht aus Versehen falsche Dateien für die Vorschau eingelesen werden, welche unser Script überhaupt nicht verarbeiten kann. In Zeile 8 wird daher geprüft, ob es sich bei dem „file.type“ wirklich um ein gültiges Bild handelt. Ist dies nicht der Fall, geben wir eine Fehlermeldung aus, welche darauf hinweist.

Nun aber ist endlich der Zeitpunkt erreicht, an welchem die Datei zum ersten Mal für die Vorschau geladen wird. Mit der „readAsDataURL“-Methode der „FileReader“-Instanz („reader“) wird die Datei geladen und in eine sogenannte Data-URL konvertiert.

Anzeigen der gewählten Datei über die Data-URL

Ein letztes Mal erweitern wir das JavaScript um folgende Codezeilen:

$(function() {
    $('#file-upload').change(function(e) {
    	// Prüfen ob die File API vorhanden ist
        if (this.files !== 'undefined' && typeof FileReader !== 'undefined') {
            // Schleife über alle gewählten Dateien
            for (var f = 0; f < this.files.length; f++) {
                var file = this.files[f];
                var reader = new FileReader();

                // Prüfen, ob auch wirklich ein Bild gewählt wurde
                if (!/image\/(jpeg|jpg|png|gif)/.test(file.type)) {
                    alert('Dateityp "' + file.type + '" wird nicht unterstützt.');
                    continue;
                }

                // EventListener hinzufügen
                $(reader).load(previewImage);

// Einlesen der Datei beginnen
                reader.readAsDataURL(file);
            }
        }
    });
});

// EventHandler für das onLoad-Event des FileReaders
function previewImage(e)
{
    var img = $(document.createElement('img'));

    // Bild mittels Data-URL laden
    $(img).attr('src', e.target.result);
    $('#preview').append(img);
}

In der markierten Zeile 13 wird ein „EventListener“ zur „FileReader“-Instanz hinzugefügt, welcher das „load“-Event überwacht. Dieses tritt ein, sobald die Datei vollständig geladen wurde.

Der Codeblock ab Zeile 21 definiert eine neue Funktion, die in Zeile 13 dem „EventListener“ mitgeteilt wurde. Hier wird in Zeile 23 ein neues <img>-Tag erstellt, welches in Zeile 25 einen neuen Wert für das „src“-Attribut zugeteilt bekommt. Das übergebene Event-Objekt „e“ enthält ein Element namens „e.target.result“, in welchem sich nach erfolgreichem Laden des Bildes die gewünschte Data-URL befindet.

Zu guter Letzt wird das neu erstellte <img>-Tag noch dem <div>-Element mit der ID „preview“ hinzugefügt. Sobald ein Benutzer nun ein Bild auswählt, sollte automatisch eine Vorschau des gewählten Bildes in der Webseite angezeigt werden, wie auf unserer Beispielseite:

https://www.checkdomain.de/blog/beispiele/html5/file-api/preview/schritt-4.html

Bitte beachte, dass große Dateien unter Umständen ein wenig Zeit zum Laden benötigen. JavaScript ist bekanntlich nicht die schnellste Programmiersprache und benötigt seine Zeit für größere Datenmengen.

Im nächsten Artikel zur HTML5 File API werde ich einen Upload mittels AJAX-Request erläutern. Die Kommentare stehen wie immer für Fragen und Anregungen zu diesem Artikel zur Verfügung.

VN:F [1.9.22_1171]
Rating: 4.8/5 (9 votes cast)
HTML5 File API - Bildervorschau mit jQuery, 4.8 out of 5 based on 9 ratings

7 Gedanken zu „HTML5 File API – Bildervorschau mit jQuery

  1. Ich bin angehender Software-Entwickler kurz vor der Prüfung !

    Dabei habe ich mich auf Webanwendungen fokusiert !

    Es ist wirklich ein unheimlich schweres Unterfangen für Neulinge,
    so einfach verständliche Tutorials zu finden !

    Daher ein ganz, ganz fettes Lob von mir an BENJAMIN !!!

    Wirklich ein ausgezeichnetes Tutorial !

    Danke !!!

    Gruß Stefan !

  2. Hallo,
    was muss man ändern damit nur ein Vorschaubild angezeigt wird ?

    1. Hi !

      Du musst einfach nur für jedes erneute „.change“ -Event verlangen, dass alle
      children von „#preview“ zuerst gelöscht werden sollen, bevor das neue bild hinzugefügt wird !

      $(function() {
      $(‚#file-upload‘).change(function(e) {

      –> $(‚#preview img‘).remove(); <–

  3. Hallo,

    ich beginne mal mit der Antwort auf die 2te Frage: Der Parameter „e“ ist in diesem Fall der Event Parameter. Im letzten Beispiel wird in Zeile 17 ein EventHandler gesetzt (die Funktion „previewImage“) welcher diesen Parameter bei Aufruf des Callbacks zur Verfügung stellt.

    Deine erste Frage ist ein wenig schwieriger zu beantworten und kommt auf deinen Anwendungsfall an. Ein Beispiel wie ich es vielleicht umsetzen würde um in der „previewImage“ Funktion einen Dateinamen zu haben wäre, das HTML Element bereits in der „for“-Schleife zu erstellen und alle benötigten Were in „data“-Attribute zu schreiben.

    1. Hallo Benjamin,

      ich hatte auch schon versucht, anstatt des onLoad-Ereignisses den Inhalt der Funktion „previewImage“ in die for-Schleife zu setzen. Funktioniert wunderbar, bis auf das Problem, dass dann der Pfad zum Bild nicht über „e.traget.result“ zur Verfügung steht. Da mir auch „file“ ausschließlich „name“, „size“, „lastModification“ und „type“ zur Verfügung stellt, steht mir in der Schleife kein Pfad zum Bild zur Verfügung.

      Alternativ hatte ich auch schon das DIV in der „for“-Schleife erzeugt und wollte über die Funktion „previewImage“ lediglich „e.target.result“ als Funktionsergebnis zurück liefern. Geht aber auch nicht bzw. ist „undefined“.

      Wie Du sicher bemerkst hast, bin ich jquery-Newbie. Mir fällt nur eine Möglichkeit ein, wo der Pfad zur Verfügung steht. Im $_FILES-Array von php. Gibt es eine Möglichkeit mit jquery darauf zu zugreifen?

      VG

    2. Hallo,

      wie gesagt, es gibt viele Lösungen und man muss schauen, welche nun genau auf deinen Anwendungsfall zutrifft. Mir ist allerdings nicht ganz klar, was genau du mit dem Pfad anstellen willst? Generell nützt er dir ja kaum etwas in einer Webanwendung, da du von einem Browser aus nicht auf das Dateisystem des Besuchers zugreifen kannst.

      Falls du einen Upload realisieren möchtest haben wir hier auch nochmal ein Beispiel zur FileAPI und dem dazugehörigen Upload: http://blog.checkdomain.de/programmierung/html5-file-api-formdata-und-xmlhttprequest2/

  4. Hallo,
    das ist ein sehr schönes Beispiel mit jquery. Vielen Dank dafür…

    Leider verzweifle ich seit 1 Tag daran, an die Funktion „previewImage“ die Parameter „f“ und „file“ zu übertragen. Diese benötige ich, um dem von mir erzeugten ImageDiv eine eindeutige ID sowie Informationen zu jeder Bilddatei zu hinterlegen.

    Mir ist auch nicht ganz klar, warum die Funktion previewImage den Paremeter e erwartet, dieser aber gar nicht übertragen wird?? Übergebe ich den Parameter explizit, funktioniert die Vorschau nicht.

    Vielleicht kann jemand Licht in Dunkel bringen. Würde mich freuen…
    VG

Schreibe einen Kommentar

Deine E-Mail-Adresse wird nicht veröffentlicht.