| Realisierung in JScript
ASP unterstützt von Haus aus keine Formulardaten, die per 'multipart/form-data' kodiert wurden. Auf die empfangenen Daten können wir daher nur im Rohformat mittels Request.BinaryRead zugreifen. Leider steht uns anschließend die Form-Kollektion nicht mehr zur Verfügung, so dass wir auch hierfür Ersatz schaffen müssen.
Im Gegensatz zu VBScript stellt uns JScript keine direkten Funktionen zur Arbeit mit binären Daten zur Verfügung. Mit Einschränkungen ist dies zwar über charCodeAt möglich, allerdings leidet die Performance bei großen Datenbeständen doch merklich.
Wir haben uns deshalb dazu entschlossen, gleich zu Beginn die gesamten Daten in das ASCII-Format zu konvertieren, um dann ausschließlich mit diesen ASCII-Werten weiterzuarbeiten. Wir speichern die Daten dazu in einer temporären Datei im Unicode-Format und lesen sie danach sofort als ASCII-Datei wieder ein:
intTotalBytes = Request.TotalBytes;
strTempFileName = Server.CreateObject('Scriptlet.TypeLib')).GUID.slice(1, 37) + '.tmp';
// Daten im Unicode-Format abspeichern...
objFSO = Server.CreateObject('Scripting.FileSystemObject');
objFile = objFSO.OpenTextFile(strTempFileName, 2, true, true);
objFile.Write(Request.BinaryRead(intTotalBytes));
objFile.Close();
// ...und im ASCII-Format wieder einlesen
objFile = objFSO.OpenTextFile(strTempFileName, 1, true, false);
strContent = objFile.Read(intTotalBytes);
objFile.Close();
Als erstes müssen wir die Zeichenkette (boundary) bestimmen, die die einzelnen Formularfelder voneinander trennt:
strBoundary = strContent.slice(2, strContent.indexOf('\r\n'));
Nun können wir die empfangenen Daten anhand dieses Strings zerlegen, wir bedienen uns einfach der split-Methode - dies vereinfacht nicht nur die Programmierung, es ist zudem auch sehr schnell:
arrItems = this._Content.split(strBoundary);
Das Array 'arrItems' enthält nun die einzelnen Formularfelder; das erste Element entspricht dem leeren String vor der ersten Grenze, das letzte dem Endekennzeichen ('--') nach der letzten Grenze - diese Elemente werden daher im folgenden nicht weiter betrachtet.
In einer Schleife wird nun jedes Element einzeln betrachtet.
Zuerst extrahieren wir - wieder mit Hilfe der split-Methode - die ersten 3 Zeilen und zerlegen anschließend die erste Zeile in die Bestandteile 'content-disposition', 'name' und - falls vorhanden - 'filename':
// Betrachten der ersten drei Zeilen, falls das Element weniger enthaelt => Fehler
// Erste Zeile enthaelt Zeilenumbuch der Grenze und ist daher immer leer...
arrLines = arrItems[i].split('\r\n', 3);
if (arrLines.length == 3){
// Zerlegen in Feldnamen und ggfs. vorhanden Dateinamen...
arrContentDisposition = arrLines[1].split('"');
In der zweiten Zeile finden wir den 'Content-type'; ist dieser nicht vorhanden, handelt es sich also nicht um eine Datei und wir können den Inhalt des Formularelementes bestimmen, 'strFieldName' enthält anschließend den Namen des Feldes, 'strFieldValue' dessen Inhalt:
if (arrLines[2] == '')
// Kein Content-Type => Formularelement
if (arrContentDisposition.length == 3){
strFieldName = arrContentDisposition[1];
strFieldValue = arrItems[i].slice(arrLines.join('\r\n').length + 2, -2);
}
Haben wir einen Content-type vorgefunden, handelt es sich bei dem Element um eine Datei; wir zerlegen dieses in Feldnamen, Dateinamen und Dateiinhalt:
if ((arrContentDisposition.length == 3) || (arrContentDisposition.length == 5)){
strFieldName = arrContentDisposition[1];
strFileName = arrContentDisposition.length == 5 ? arrContentDisposition[3] : '';
if (arrLines[2].toLowerCase().indexOf('content-type: ') == 0){
strContentType = arrLines[2].slice(14);
strContent = arrItems[i].slice(arrLines.join('\r\n').length + 4, -2);
}
}
Und das war es dann eigentlich auch schon. Um das ganze etwas leichter anwenden zu können, haben wir alles in ein Objekt verpackt, Kollektionen für den Zugriff auf die Form- und Dateielemente erzeugt und das ganze mit einer Fehlerbehandlung versehen.Sie können Sich den vollständigen, kommentierten Quellcode herunterladen.
Zusätzlich haben wir noch einige nützliche Funktionen integriert, die wir im folgenden Abschnitt detailliert beschreiben werden. |