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.

  • http://imwill.com Hen

    Sehr schöner Artikel. Genau das habe ich gesucht. Danke! :)

  • Vijay

    Is this will support IE 7 onwards

  • Samuel Nepomuk

    Hey Vijay, FormData support for internet explorer is very bad http://caniuse.com/#search=FormData – But you can use an ajax upload iframe hack plugin as fallback. All modern browser understand the html5-way. All the best!

  • Florenz

    Moin, ich bin etwas neu auf dem Gebit Ajax etc…
    in meiner Index-Datei habe ich jetzt folgenden Formularteil:

    Wie kann ich nun in meiner fileupload.php auf datei bzw test zugreifen? ich habe es wie folgt versucht:
    echo $_FILES[‚datei‘];
    echo $_POST[‚test‘];
    Muss ich bei:
    data.append(‚file‘, this.files[0]);
    data.append(‚foo‘, 1);
    noch die parameter ‚file‘ und ‚foo‘ setzen?
    Was genau bewirken diese?
    Vielen Dank für eine Antwort…

  • Florenz

    Sry, Formularteil vergessen…

  • Florenz

    input type=“file“ name=“datei“ id=“fileUploader“
    input type =“text“ name=“test“

  • Florenz

    Da er mir auch einige Fehler angezeigt hatte, habe ich die Funktion auch etwas abgeändert:

    $(‚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() {
    alert(„moin“);
    }
    });

    })

  • Florenz

    Habe es jetzt doch zum laufen bekommen, funktioniert alles bestens!
    Vielen Danke für den Post! Und sorry für den Spam….

  • http://www.besseronlineblog.de Phillip

    Hallo, da der Code oben nicht ganz korrekt ist und Florenz den korrekten Code leider nicht mehr gepostet hat, hier der Lauffähige Code noch einmal komplett. Unter Umständen ist die übertragbare Dateigröße in der php.ini anzupassen (Parameter „post_max_size“).

    Hier der Code der HTML File:
    ——————————————————————-

    Ajax Fileupload

    $( document ).ready(function() {
    $(‚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

    }
    });
    });
    });

    ——————————————————————-

    Hier der Code der fileupload.php (im gleichen folder)
    ——————————————————————-

    ——————————————————————-

  • http://www.besseronlineblog.de Phillip

    Na super, PHP Code wird offensichtlich ausgefiltert.

    Geht es so:

    if (!empty($_FILES)) {
    $tempFile = $_FILES[‚file‘][‚tmp_name‘];
    move_uploaded_file($tempFile,$_FILES[‚file‘][‚name‘]);
    }

  • http://www.besseronlineblog.de Phillip

    $tempFile = $_FILES[‚file‘][‚tmp_name‘];
    move_uploaded_file($tempFile,$_FILES[‚file‘][‚name‘]);

  • http://www.besseronlineblog.de Phillip

    na super. PHP Code wird offensichtlich ausgefiltert :(

  • http://misterunknown.de misterunknown

    Hallo. Danke für deinen Beitrag, er hat mir sehr geholfen.
    Hier noch 2 Anmerkungen:
    1. für die Copy&Paster hier: In dem Skript oben fehlt ganz am Ende eine normale Klammer zu und das Semikolon dahinter.
    2. Wer den Upload in eine Funktion packen möchte, der nicht das Input-Feld direkt übergeben wird, darf es nicht per jQuery selektieren, sondern muss den Weg über document.getElementById(‚foo‘) gehen, da ein jQuery-Objekt nicht die Eigenschaft files hat.

    Ansonsten hat alles super funktioniert ;)

    Grüße, Marco

  • William Keluman

    Hi Marco, danke für deinen Kommentar. Punkt 1 habe ich im Text oben ergänzt – vielen Dank für den Hinweis!

  • http://blog.alexander-fischer.org/ Alex

    Schöne Lösung. Gefällt mir.
    Kleiner Hinweis für den Ajax-Aufruf mit jQuery: Seit Version 1.8 ist der success-Callback deprecated, stattdessen sollte man mit done() arbeiten:

    // Ajax-Call
    $.ajax({
    url: ‘/fileupload.php’,
    data: data,
    type: ‘POST’
    processData: false,
    contentType: false
    }).done(function(response){
    //successful
    console.log(response);
    }).fail(function(e){
    //error
    console.error(e);
    });

  • http://www.gogabie.com/north-face-black-gloves-denali-uk-p-321.html North Face Black Gloves Denali UK

    It astounds me that PTSD (or whatever name used by ‚experienced and participated in mass murder‘) took so very long being named real. For a nice and traumatized by lesser incidents like hitting a deer, or getting in a fender bender that left me nervous and edgy for the days. Full scale war that would be that.
    North Face Black Gloves Denali UK http://www.gogabie.com/north-face-black-gloves-denali-uk-p-321.html