Ajax Fileupload

Zugriffe: 7857 starstarstarstarstarstarstarstarstarstar Bewertung:3,22 (9 Bewertungen) 02.05.2009

Wer sich mit der Entwicklung von Webanwendungen beschäftigt, kommt sicher nicht umhin, auch einmal ein Upload-Formular zu erstellen. In Zeiten des "Web 2.0" (wofür diese Bezeichnung auch immer stehen mag) werden die Wünsche und Ideen auch immer anspruchsvoller. Und so verwunderte es nicht all zu sehr, dass mit dem AJAX-Hype der Gedanke aufkam, so ein schönen Dateiupload per AJAX zu erledigen. Es folgte ziemlich schnell die Erkenntnis, dass dies nicht geht und wahrscheinlich auch künftig so nicht gehen wird, will man sich auf den klassischen XML-Request beschränken.

Eine schon vor dem AJAX-Hype viel genutzte Variante war, die Datei, die zum Server zu übertragen ist, über ein nicht sichtbares Frame zu senden. Anfänglich wurde hierzu das Frameset genutzt, wobei ein Frame mit 0 definiert wurde, so dass der dort stattfindende Request für den Benutzer der Seite verborgen blieb. In der Folgezeit ging man jedoch immer mehr dazu über, das iframe-Element zu nutzen.

 Dies ist bis heute die wohl weit verbreiteste Form der "versteckten" Hintergrundübertragung von Datein zum Server. Und genau vor diesem Hintergrund machte ich mich die Tage auf, das Netz zu durchforsten, was es an Ideen schon gibt, so dass man einen - sagen wir mal kompfortablen - Dateiupload erstellen kann.

Die aus meiner Sicht vielversprechendste Lösung bot sich bei Andrew Valums, der ein entsprechendes Javascript unter der MIT-License veröffentlicht hat. Vieles, was diese Lösung bietet, ist eigentlich genau das, was man sich - will man es denn so bezeichnen - unter einem AJAX-Upload vorstellt. Andrew hat dabei den Einsatz mit prototype als auch jQuery berücksichtigt. Besonders gelungen ist auch meiner Sicht, die Umsetzung des Klickevents zum Anzeigen des input-File-Dialoges. Hierbei wird die Mausbewegung im document überwacht und sobald sich die Maus über dem Bereich befindet, der den eigentlichen Dialog öffnen soll, wird das nicht sichtbare input-File-Element unter dem Mauszeiger plaziert. Ein jetzt erfolgender Klick führt somit immer zum Öffnen des File-Dialoges.

Position input file Element

Da über die CSS-Attribute des input-File-Elementes dieses vollständig unsichtbar gemacht werden kann, bekommt der Benutzer von diesem Verhalten nichts mit.
Nachteilig an der Version von Andrew ist jedoch, dass beim Verlassen des Bereiches das input-File-Element noch mitwandert und ich faktisch auch ausserhalb meines eigentlich gedachten Upload-Bereiches den File-Dialog öffnen könnte. Derartiges kann bei Benutzern leicht zu Irritationen führen. Die Lösung liegt derweil auf der Hand - man positioniert einfach das input-File-Element außerhalb des sichtbaren Bereiches.

 Fehlposition input file

Weiter positiv in der Umsetzung fand ich, dass die drei klassischen Eventhandler mit implementiert sind.

Als erstes kann man auf der Anwendungseite reagieren, sobald eine Datei über den File-Dialog ausgewählt wurde. Als Parameter gibt Andrew dann den Dateinamen als auch die Dateierweiterung mit.
Ein weiteres Mal kann vor dem Absenden der Datei zum Server noch einmal auf Anwendungsseite reagiert werden, wobei auch hier der Dateiname und die Dateierweiterung als Parameter zur Verfügung stehen. Zu guter Letzt kann man entsprechend noch reagieren, wenn dann die Datei zum Server übertragen wurde, der eigentliche Upload also fertig ist.

Muss man im Zusammenhang mit dem Dateiupload noch weitere Daten zum Server mit übertragen, so kann man über das option-Objekt bei der Initialisierung ein data-Objekt mit angebengeben. Bei der Vorbereitung des Postbacks werden dann entsprechende input-Hidden-Elemente angelegt und mit zum Server übertragen.

// Create hidden Input element for each data key
for (var prop in Setting.data) {
    var el = d.createElement("Input");
    el.type = "hidden";
    el.name = prop;
    el.value = Settings.data[prop];
    form.appendChild(el);
}

Eines hatte ich jedoch vermisst. Was passiert eigentlich, wenn ich einen Multifileupload mit dieser Lösung umsetzen möchte. Eigentlich passte soweit alles, bis ich eine Datei auswählte, die in der Liste schon vorhanden war. Im onComplete-Eventhandler jetzt die Datei allein über den Namen zu identifiezieren war zum Scheitern verurteilt. Ich brauchte also einen Key, der im onChange-Eventhandler schon zur Verfügung stand, so dass ich diesen auf Anwendungsseite verarbeiten konnte, um dann bei Abschluss des Uploads den richtigen Eintrag in der Liste wiederzufinden. Schön wäre, wenn es soetwas wie eine GUID im Javascript gäbe.

Hier fand ich dann eine Lösung, die mir hier weiterhelfen sollte.
Sicher gibt es auch andere, vielleicht auch einfachere Lösungsansäntze (string + counter) für mein Problem mit dem Key, doch schwebte mir in der Tat dieser GUID-Gedanke im Kopf, so dass ich diese letztlich favorisierte. Also baute ich mir schnell ein GUID-Objekt, und modifizierte den Rückgabeparameter in den Eventhandlern entsprechend.

Das eigentliche Senden der Datei erfolgt dann auch wieder über ein für den Benutzer nicht sichtbares iframe-Element. Gut fand ich auch in diesem Zusammenhang, das Andrew sich auch das entsprechend für den Dateiversandt erforderliche Formular gekümmert und ein separates form-Element mit dem entsprechenden enctype-Attribute (enctype="multipart/form-data") angelegt hat.

Insgesamt eine runde Sache, die Andrew mit seinem Javascript hier erstellt hat.

Da ich prototype nicht einsetze, habe ich die Scriptdatei für meine Bedürfnisse angepasst und stärker dem Umstand Rechnung getragen, dass in meinen Projekten jQuery zum Einsatz kommt.
Andrew setzt hingegen kein spezielles Framework voraus.


1 Kommentar
Thommy Thommy Donnerstag, 17. Mai 2012
Cooler Artikel! Habe gerade lange via Google nach guten Lösungen für File Uploads via Ajax gesucht. Bin dann drauf gekommen, dass das inzwischen sogar via HTML5 geht, Code gibts hier: http: //www .solife .cc/ blog/ ajax-file-upload-formdata-xhr2 .html

Vielleicht hilfts je irgendjemanden :-)

Greets Thommy

Neuen Kommentar verfassen

Bestätigungscode