da heut im Forum wieder mal ein Thema zum Punkt Upload mit AJAX erörtert wurde, habe ich dies zum Anlass genommen, einmal darzulegen, warum es nicht möglich ist, soetwas mittels AJAX zu Bewerkstelligen.
Es soll natürlich auch zur Sprache kommen, wie man einen Upload trotzdem so aussehen lassen kann, als ob er per AJAX gesteuert wird.
Ich werde auf umfangreiche Erläuterungen des Codes verzichten, das Meiste ist im Code selbst kommentiert und m.E. gut verständlich.
Warum kann es keinen Upload mit AJAX geben?
Diese Frage ist recht einfach beantwortet:
Um etwas über einen XMLHTTPRequest oder Javascript allgemein an einen Server zu Senden, muss man Daten haben.
Will man also eine Datei von einem Clientrechner mittels AJAX uploaden, geht dies aus dem schlichten Grund nicht, dass man mit den genannten Techniken nicht im Dateisystem des Clienten lesen kann.
Wie aber kann man es nun doch anstellen?
Die 1. Frage wäre, wie man sich solch einen Upload überhaupt vorstellt? Sehr umfangreich sind die Anforderungen eigentlich garnicht.
- Er sollte im Hintergrund ablaufen, ohne die aktuelle Seite neu geladen werden muss
- Die aktuelle Seite sollte Feedback über den Erfolg des Uploads erhalten
Wie geht man es nun an:
Man benötigt ...
- ein herkömmliches Formular mit Upload-Feld
- ein serverseitiges Skript, welches den Upload entgegennimmt, und eine Statusmeldung für den Absender bereithält
- ein clientseitiges Skript, welches folgende Dinge erledigt:
- Erzeugen eines versteckten <iframe>'s im Dokument, welches als Zielfenster für das Formular dient
- Überwachen des load-Events dieses <iframe>'s
- Auslesen der Statusmeldung aus dem Empfänger-Dokument, sobald dies geladen ist
- Ausgabe dieser Statusmeldung im Absender-Dokument
Code des Absenders:
Code :
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 | <body>
<form name="formularName" enctype="multipart/form-data" method="post" action="load.php">
<input type="file" name="file" >
<input type="submit" value="Senden" >
</form>
<ul id="zielContainerId"><li style="font-size:1.5em;list-style-type:none">Uploads</li></ul>
<script type="text/javascript">
<!--
(
function(ns,f,t,r)
{
var _this={
'ns':ns,
't':document.getElementById(t),
'r':r,
'f':document[f],
//vor dem Senden des Formulares
'send':function()
{
//'eindeutigen' Namen für das iFrame generieren
var n=ns+new Date().getTime();
//iFrame in das Dokument einfügen
this.t.innerHTML+='<li id="'+n+'" style="display:none">'+
'<iframe src="about:blank" name="'+n+
'" onload="'+ns+'.callback(this)" '+
'width="300" height="300"></iframe></li>';
//Zielfenster des Formulares neu setzen
this.f.target=n;
//weiter zum Sendevorgang
return true;
},
//Verarbeitung der 'Antwort'
'callback': function(o)
{
// je nach Browser sind
// 2 alternative 'Ansprechpartner' vonnöten
try{//kein IE
this.t.innerHTML+=
o.contentDocument.getElementById(this.r).innerHTML;
}catch(e){//IE
try{
this.t.innerHTML+=
o.contentWindow.document.getElementById(this.r).innerHTML;
}catch(e){return;}
}
//iframe entfernen
this.t.removeChild(document.getElementById(o.name));
//Formular zurücksetzen
this.f.reset();
}
}
//Objekt global verfügbar machen
window[ns]=_this;
//submit-Event des Formulares überwachen
_this.f.onsubmit=function(){return window[ns].send();}
}
)( //frei wählbarer, aber global eindeutiger Identifier
'uploader',
//Name des Formulares
'formularName',
//ID des Elementes,indem die Antwort ausgegeben wird
'zielContainerId',
//id des Elementes im Formularziel, das die Meldung beinhaltet
'responseContainerId');
//-->
</script>
</body> |
und der Empfänger
Code :
1 2 3 4 5 6 7 8 9 10 11 | <ul id="responseContainerId"><li><?php
if(isset($_FILES['file']))
{
//Abgesehen von der Ausgabe sollte die Datei natürlich
//noch verarbeitet oder verschoben werden
echo (!$_FILES['file']['error'] && $_FILES['file']['size'])
? '<strong>'.$_FILES['file']['name'].'</strong> hochgeladen'
: 'Upload-Fehler';
}
?></li></ul> |
...das war es schon, ich hoffe es ist ausführlich genug für einen Codeschnipsel

Die Nutzung von innerHTML möge mir bitte verziehen werden, sie hat Gründe:
- bei der Erzeugung des iframe hat der InternetExplorer Probleme, das iframe als Zielfenster des Formulares zu Finden, wenn das iframe per DOM erzeugt wird
- auch das Verschieben von Knoten zwischen Dokumenten ist im InternetExplorer nicht möglich(was übrigens den Spezifikationen des w3c entspricht), weshalb ich innerHTML auch beim Auslesen der Antwort verwendet habe.
Anbei eine lauffähige Demo.(up.zip)
lg Sven
Nachtrag:
Da öfters mal Nachfragen und Wünsche zu dem Beispiel kamen, hier ein Update.
Es ermöglicht nun auch die Verwendung mehrerer Upload-Felder in einem einzigen Formular bzw. die Verwendung mehrerer Formulare mit Uploadfeldern mit dem selben Zielcontainer zur Ausgabe der response.
Die Function erwartet nun eine beliebige Anzahl von Argumenten(für jedes Formular eines) in Objektform.
Beispielaufbau solch eines Objektes:
Code :
1 | {f:'form1',t:'zielContainerId',r:'responseContainerId'} |
- f:'form1'
...der Name des Formulares - t:'zielContainerId'
...die ID der Liste, welche die Antwort anzeigen soll - r:'responseContainerId'
...die ID der Liste, in welcher PHP bei der Antwort die Details vorrätig hält
Anbei wieder eine lauffähige Demo(upv2.zip), getestet mit
FF
Chrome
Opera
IE 6+8





Bereiche
Kategorien
Forum - Webmaster & Internet




