Artikel - Detailansicht

Icon Aktuelles Mehrfacher Fileupload - Die komplexe Variante, Teil II

Kommen wir jetzt zum Template main.cfm.
Zuerst müssen wir uns eine Struktur erstellen, mit der wir unsere Dateinamen-Daten im Browser speichern können. Dazu benutzen wir ein WDDX-Recordset, das im Prinzip einem CF-Queryset entspricht. Die Javascript-Library WDDX.js von Allaire liefert eine komplettes Funktionsset zum Arbeiten mit dieser Struktur.

Der Code zu Begin des Scripts erzeugt ein leeres Queryset (auf Serverseite):

<CFSET qDummy = QueryNew("clientfile, serverfile")>

Das Queryset ethält die Spalte clientfile, dort werden wir den Client-Dateinamen der upgeloadeten Datei speichern. In der Spalte serverfile speichern wir dann den Namen, den die Datei auf dem Server erhält.
Dieses Queryset konvertieren wir (immer noch auf dem Server) mit dem <cfwddx>-Tag in eine Javascript-Struktur:

<!--- Queryset in JS-Recordset konvertieren --->
<SCRIPT LANGUAGE="JavaScript" TYPE="text/javascript">
<cfwddx action="CFML2JS" input="#qDummy#" toplevelvariable="rsFilePaket">
</SCRIPT>


Die Javascript-Struktur ist ein WDDX-Recordset und heist hier rsFilePaket. Sie ist vom Typ Obejct und enthält Methoden zur Manipulation der Daten.
Das <cfwddx>-Tag erzeugt Javascript, der erst im Browser interpretiert wird, deshalb dürfen die <SCRIPT>-Tags um das <cfwddx> nicht vergessen werden!

Kommen wir zum Hauptformular:

<form action="upload.cfm" name="f" method="post" >
  <input name="wData" type="hidden" value="">
  <select name="sFileNameCtr" size="5">
  <option>|--------------loading----------------------|
  </select><br>
  <input type="Button" value="Datei hinzufügen" onclick="win()">
  <input type="Button" value="Upload" onclick="upload()">
</form>


Das Hidden-Element wData dient später als Container für das WDDX-Recordset. Die Selectbox soll die Liste der bereits zum Server übertragenen Dateien aufnehmen und dem User anzeigen. Mit dem Button 'Datei hinzufügen' öffnen wir über die JS-Funktion win() ein Popupfenster mit der bereist besprochenen Datei select.cfm.

Um die Platzhalter in der Selectbox nach dem Laden der Seite zu löschen wird im <Body>-Tag die Selectbox nach dem Laden gelöscht:

<body onload="document.f.sFileNameCtr.options.length=0">

Kommen wir nun zur JS-Funktion addFile(), die wie erläutert vom Popup-Fenster aufgerufen wird. Bei Aufruf werden die JS-Variablen sClientFileName, sServerFileName und iFileLen generiert.
Der Aufruf von addFile() bedeutet, dass ein neues File auf den Server geladen wurde und die übergebenen Daten nun im WDDX-Recordset gespeichert werden wüssen, zusätzlich muss zur Anzeige für den User der Client-Filename in die Selectbox geschrieben werden.
Zuerst müssen wir im Recordset rsFilePaket eine neue Reihe für den neuen Datensatz hinzufügen: Dazu rufen wir die Methode addRows() des Objects rsFilePaket aus:

rsFilePaket.addRows(1);

Dann speichern wir die der Funktion übergebenen Dateinamen in den jeweiligen Spalten des Recordsets:

idx=rsFilePaket.getRowCount()-1;
rsFilePaket.clientfile[idx]=sClientFileName;
rsFilePaket.serverfile[idx]=sServerFileName;


Damit sind die Daten im Recordset gespeichert. Zur Anzeige für den User schreiben wir die Daten noch in die Selectbox, indem wir ein neues Option-Objekt erzeugen:

document.f.sFileNameCtr.options[document.f.sFileNameCtr.options.length]=
new Option(sClientFileName+' ('+iFileLen+') Bytes',');


Dabei wird die Länge der Datei als Feature noch mit angezeigt.

Fehlt jetzt nur noch die Übertragung des Hauptformulars aus dem Template main.cfm.
Als Submit-Button definieren wir hier einen normalen Button, der die Javascript-Funktion upload() aufruft:

<input type="Button" value="Upload" onclick="upload()">

In dieser Funktion wird dann die ganze Arbeit für den Submit erledigt.
Zuerst müssen wir das Recordset-Object rsFilePaket in einen String konvertieren, denn nur Strings können zum Server mit dem Formular übertragen werden. Dieser Vorgang nennt sich Serializieren (siehe vorherige WDDX-Artikel).
Dazu müssen wir erst ein WddxSerializer-Object erzeugen. Die WDDX-Library stellt dazu den Konstruktor WddxSerializer() zur Verfügung:

ser=new WddxSerializer();

Mit der Methode serialize() des WddxSerializer-Object können wir ein WDDX-Recordset serializieren:

wData=ser.serialize(rsFilePaket);

In der Variable wData liegt jetzt unser Datenpaket rsFilePaket als String gespeichert.
Diesen String können wir nun problemlos zum Server schicken. Der String muss dazu nur noch ins Form-Elemente wData geschrieben und per JS der Submit ausgelöst werden:

document.f.wData.value=wData;
document.f.submit();


Jetzt werden die Daten des Formulars mit den Dateinamen übertragen. Es werden an dieser Stelle keine Dateien selbst übertragen, denn die liegen schon alle auf dem Server im Verzeichnis temp!

Die Datei upload.cfm erhält nun die FORM-Variable FORM.wData beim Aufruf als Parameter übergeben. Durch ein Deserializieren mit dem <cfwddx>-Tag wird dann zuerst wieder die Datenstruktur rekonstruiert und ein Queryset erzeugt:

<cfwddx action="WDDX2CFML" input="#FORM.wData#" output="qFileSet">

Dann loopen wir über das Queryset und lesen bei jedem Durchlauf den Clientfilenamen und den Serverfilenamen aus. Da wir die Filenamen mit kompletten Pfad gespeichert haben, benutzen wir dabei die Coldfusion-Funktion GetFileFromPath() um an den 'reinen' Dateinamen zu gelangen:

<cfset sClientFileName=GetFileFromPath(qFileSet.clientfile)>
<cfset sServerFileName=GetFileFromPath(qFileSet.serverfile)>


In der CF-Variable sServerFileName ist jetzt der Dateiname gespeichert, unter dem die Datei (die gerade im Loop behandelt wird) im Verzeichnis temp gespeichert liegt.
In der Variable sClientFileName haben wir den Dateinamen, unter den die Datei in das Verzeichnis filestore geschrieben werden soll. Deshalb führen wir jetzt eine Verschiebung der Datei + Namensänderung durch:

<CFFILE ACTION="move" SOURCE="#sTempPath#\#qFileSet.serverfile#"
DESTINATION="#sStorePath#\#qFileSet.clientfile#">


Und damit ist die Arbeit getan.

Das Temp-Verzeichnis sollte in regelmässigen Abständen durch einen automatischen Task von Dateileichen bereinigt werden, denn bricht ein User den Vorgang ab, bleiben die bereits übertragenen Dateien auf dem Server.

Anzumerken bleibt noch, dass Client- und Serverfilenamen im Normalfall gleich sind, und nur wenn es im Temp-Verzeichnis bereits eine Datei gleichen namens gibt, wird ein neuer Name für die Datei generiert.

<!--- DummyQueryset erzeugen --->
<CFSET qDummy = QueryNew("clientfile, serverfile")>

<!--- WDDX-Lib einbinden --->
<SCRIPT LANGUAGE="JavaScript" TYPE="text/javascript" src="wddx.js"></SCRIPT>

<!--- Queryset in JS-Recordset konvertieren --->
<SCRIPT LANGUAGE="JavaScript" TYPE="text/javascript">
<cfwddx action="CFML2JS" input="#qDummy#" toplevelvariable="rsFilePaket">
</SCRIPT>


<head>
  <title>main.cfm</title>
</head>

<body onload="document.f.sFileNameCtr.options.length=0">

<b>Mehrfacher Fileupload V2</b><br>

<SCRIPT LANGUAGE="JavaScript" TYPE="text/javascript">
function addFile(sClientFileName,sServerFileName,iFileLen){
  <!--- Datensatz in Recordset speichern --->
  rsFilePaket.addRows(1); //1 reihe dazu,
  idx=rsFilePaket.getRowCount()-1;
  rsFilePaket.clientfile[idx]=sClientFileName;
  rsFilePaket.serverfile[idx]=sServerFileName;


  <!--- Selectbox füllen --->
  document.f.sFileNameCtr.options[document.f.sFileNameCtr.options.length]=
  new Option(sClientFileName+' ('+iFileLen+') Bytes',sClientFileName);


  alert(rsFilePaket.getRowCount()+' Dateien gespeichert');
}


function upload(){
  ser=new WddxSerializer();
  wData=ser.serialize(rsFilePaket);
  document.f.wData.value=wData;
  document.f.submit();
}


var hwin=0;
function win(){
  if(hwin){
    if(hwin.closed){hwin=0;win();}
    else {hwin.close();hwin=0;win();}
    }
  else{
    hwin=window.open("select.cfm", 'remote',
    'menubar=no, scrollbars=no, directories=no, status=no, resizable=yes, width=300, height=150', true);
  hwin.focus();
  }
} //ende function win()
</SCRIPT>

<form action="upload.cfm" name="f" method="post">
  <input name="wData" type="hidden" value="">
  <select name="sFileNameCtr" size="5">
  <option>|--------------loading----------------------|
  </select><br>
  <input type="Button" value="Datei hinzufügen" onclick="win()">
  <input type="Button" value="Upload" onclick="upload()">
</form>

</body>


Steffen Goldfuss steffen@goldfuss.de - 18.12.2000

Zurück


Das deutsche ColdFusion-Forum cfml.de ist das Portal für Einsteiger und Experten zum Thema ColdFusion und der ColdFusion Markup Language (CFML).

© 2017 Webdesign & Hosting: CHC ONLINE Kassel | SOLVA Content-Management-System CMS
Urlaub-Angebote.de - Urlaub mit Bestpreis-Garantie buchen