Ajax File Upload mit HTML5 und XHR2 (ohne Plugin oder Iframe-Hack)

Ajax File Upload mit HTML5
In wenigen Zeilen zum File-Ajax-Call

Bilder oder andere Dateien via Ajax zu übermitteln war mit XMLHttpRequest Level 1 bis dato eine äußert unschöne Angelegenheit – denn nur einfache Daten konnten gesendet werden. Um den Ajax-File-Upload trotzdem zu realisieren, verwendeten Webworker deshalb Iframe-Hacks in verschiedensten JavaScript-Plugins. XHR 2 bietet nun allerdings die Möglichkeit die Scripts der bisherigen Webseiten aufzuräumen und ganz nativ Dateien via Ajax an den Server zu senden.


FormData() macht es möglich

XHR 2 bietet mit dem FormData()-Interface nun die Möglichkeit Bilder oder andere Dokumente für den darauffolgenden Ajax-Call aufzubereiten. Nach dem Initialisieren in einer Variable, kann via append()-Methode jeder einzelne Parameter hinzugefügt werden. Ein einfaches Beispiel mit jQuery:


$(‘body’).on('change', '#fileUploader', function() {

    // Post-Daten vorbereiten
    var data = new FormData();
    data.append('file', this.files[0]);
    data.append('foo', 1);

    // Ajax-Call
    $.ajax({
        url: ‘/fileupload.php’,
        data: data,
        type: ‘POST’
        processData: false,
        contentType: false,
        success: function(evt) { // Bild anzeigen }
    });

});

Das File-Input mit der ID #fileUploader triggert bei jeder Änderung (und somit jedem Upload) die change-Funktion. Via FormData() und .append(key, value) werden die einzelnen Parameter für den Call vorbereitet. Mit this.file[0] gelangt man zur ersten hochgeladenen Datei dieses Inputs. Multi-File-Uploads via Ajax können somit ebenfalls problemlos durchgeführt werden.

Der $.ajax()-Methode von jQuery müssen folgende Konfigurationen hinterlegt werden: processData und contentType auf false.

Im PHP-Dokument fileupload.php kann nun ganz normal mit $_FILE[] auf die Dateien bzw. $_POST[] auf die anderen Parameter zugegriffen werden.

Browser-Support

Gute Nachricht: Moderne Browser (Firefox, Chrome, Opera, Safari) unterstüzen XHR2 und somit FormData() komplett. Der Internet Explorer leider erst ab Version 10. Wer an Backends oder anderen modernen Webseiten bastelt, die also nicht Browserübergreifend gleich funktionieren müssen, eine denkbare Lösung. Alternativ kann natürlich auch ein Fallback zu einem Java-Script Plugin mit Iframe Hack eingerichtet werden.

Head JS – Scriptdateien parallel und asynchron Laden

„it’s becoming a core client side development tool for many“

Vor über fünf Jahren genügte noch ein einziges Java-Script-File, um einem ganzen Webportal Interaktivität einzuhauchen. Niemand redete damals über komprimierte Scripte, Framework-Plugins, die neueste JavaScript-Engine im Browser oder clientseitige Performance-Optimierungen. Durch den Siegeszug von Frameworks wie jQuery oder Mootools, dazugehörige Erweiterungen und immer umfangreichere Weboberflächen, wurde das Bild des Internets stark verändert – Und das ist auch gut so. Doch all diese Script-Wunder müssen erstmals vom Browser des Benutzers heruntergeladen werden. Damit dies schnell von statten geht, basteln die Hersteller an immer effektiveren Java-Script Engines. Doch auch jene, die sich Webworker nennen, müssen Zeit investieren, um ihre Projekte dahingehend zu optimieren. Genau an diesem Punkt setzt Head JS an.

Doch was passiert eigentlich beim Laden einer Website? Zuerst werden die im <head>-Bereich verlinkten Stylesheet- und Script-Files heruntergeladen. Abgesehen von ganz modernen Browsern, funktioniert dies nicht parallel, sondern nacheinander. Erst wenn alle Dateien geladen wurden, beginnt das Markup-Rendering und somit auch der für den Benutzer interessante Teil: Die Website erscheint. Schlaue Frontend-Entwickler platzieren deshalb ihre Script-Files an das Ende des Dokumentes. Durch das zuerst durchgeführte Rendering, erscheint es, als würde die Seite schneller laden, da die Script-Dateien erst heruntergeladen werden, wenn die Website schon sichtbar ist. Doch es gibt noch Optimierungsbedarf.

Head JS

Das Konzept von Head JS ist simpel und effektiv: Im Kopfbereich der Seite wird lediglich ein einziges Script-File eingebunden. Alle weiter benötigten Dateien werden parallel via Funktionsaufruf nachgeladen und in der gewünschten Reihenfolge ausgeführt. Der Vorteil liegt klar auf der Hand: Das Rendering der Seite startet sofort und die noch fehlenden Java-Script-Dateien werden, durch den gleichzeitigen Abruf, rascher vom Browser heruntergeladen. Es wird außerdem eine spezielle Funktion “gefeuert” sobald alle Dateien bereit sind. Durch diese ist es möglich, mitten im <body>-Bereich Scripte einzufügen, die erst dann ausgeführt werden, wenn beispielsweise die jQuery-Bibliothek geladen wurde.


Ein einfaches Beispiel zum Laden von drei Script-Dateien mit Head JS:

head.js("/path/to/jquery.js", "/google/analytics.js", "/js/site.js");

Doch Head JS macht mit seiner Größe von 2.30kb noch mehr: Es befüllt den <html>-Tag mit einer Vielzahl nützlicher Klassen (Browser-Typ, Fenstergröße, Funktionalität von einzelnen CSS3-Eigenschaften, Page-Routes und noch einige mehr). Außerdem wird versprochen, dass ausgewählte HTML5-Tags durch das “Kopf-Script” in allen Browsern funktionsfähig sind.

Meine ersten Praxis-Tests verliefen erfolgreich bis durchwachsen. Die Senkung der Seitenladezeiten, klappt durch den parallelen Aufruf in jedem Fall erfolgreich. Die neuen CSS-Klassen sind praktisch und machen so manches zusätzlich erstellte Stylesheet-File obsolent. Probleme gab es lediglich mit dem Internet Explorer: Das Nachladen des selectivizr-Script mit Head JS führte zu regelmäßigen Abstürzen oder Fehlermeldungen des Browsers. Auch Umdenken beim Ausführen von Scripten mitten im <body>-Bereich ist nun angesagt, vor allem wenn dies initial und später via Ajax-Call passiert.

Ein rascher Einstieg in diese neue Herangehensweise ist dank der informativen Website von Head JS gegeben. Ob Webworker zukünftig wirklich nur mehr ein einziges JavaScript-File direkt einbinden müssen und ob die Performance-Steigerung überall erfolgt, werden weitere Tests zeigen. Es wird laufend an Head JS gearbeitet und daher sollte man dieses Projekt im aktuellen Jahr bestimmt nicht aus den Augen verlieren.