![]() |
Stefan Falz
|
|
| |
| E-Mail: | |
|---|---|
| Homepage-URL: |
Bei Fragen zu diesem Beitrag bitte den Autor des Beitrags kontaktieren!
Bevor Sie beginnen, diesen Artikel zu lesen, möchte ich Sie gleich darauf hinweisen, daß einige Vorarbeiten nötig sind, um das Beispiel auf Ihrem lokalen Webserver oder einem Internetserver ausführen können. Als Betriebssystem wird Windows 95, Windows 98 oder Windows NT ab Version 4.0 vorausgesetzt. Weiterhin muß ein ASP-fähiger Webserver, wie z.B.: PersonalWebServer 4.0 oder InternetInformationServer ab Version 3.0 sowie ein ASP-Modul ab Version 4.02.0685 installiert sein. Frühere Versionen der genannten Komponenten unterstützen jeweils nur einen Teil der erforderlichen Routinen.
Zu einem der noch eher gemiedenen Themen in der modernen Internetwelt gehört
auch das direkte Hochladen von Dateien im Browser. Obwohl jeder ein
Eingabeformular mit einem Eingabefeld für Dateien erstellen kann (siehe
Datei-Buttons in HTML), sieht man dies
äußerst selten. Dies liegt zum einen daran, daß serverseitige Programme, die das Auslesen der Datei aus dem übermittelten HTTP-Stream und das anschließende Speichern der Datei auf dem Server übernehmen, recht teuer sind und wohl auch an der Tatsache, daß der Internetsurfer Schreibrechte auf einem Verzeichnis des Webservers benötigt, da unter ASP solche Aktionen mit dem Standardkonto
IUSR_Rechnername vorgenommen werden. Aber auch diese Programme haben Ihre
Berechtigung, da es mit ASP derzeit noch nicht möglich ist, Binärdateien, wie
Bilder oder Programme zu speichern. Ein solches Modul, daß natürlich einiges
mehr an Komfort, wie z.B automatische Übernahme der Sendedaten und der
Dateinamen in eine Datenbank, automatische Zuordnung zu bestimmten Einträgen,
usw. bereitstellt, finden Sie unter
http://www.asp-solutions.de.
<html>
<head>
<title>Dateiupload per ASP</title>
</head>
<body>
<form method="POST" action="empfang.asp" enctype="multipart/form-data" target="_new">
<input type="file" name="File" size="50"><br>
<input type="submit" value="DATEIUPLOAD STARTEN" name="Submit">
</form>
</body>
</html>
Anders als in einem "normalen" Formular, in dem die Angabe enctype="..." entfallen kann, muß bei der Versendung von Dateien diese Angabe den Wert "multipart/form-data" haben, da der Browser ansonsten nicht erkennt, daß er die Datei entsprechend codiert an den Server senden soll. Bei fehlerhafter oder fehlender Angabe wird das Formular ganz normal behandelt, d.h. der Browser erhält lediglich den ausgewählten Dateinamen inkl. Pfad, aber nicht den Inhalt der Datei. Weiterhin kann man im Browser auch gleich angeben, welche Dateitypen ausgewählt werden dürfen und die max. Dateigröße in Byte, aber diese Funktionen lassen sich sehr leicht umgehen. Daher ist in dem Beispiel eine serverseitige Abfrage auf diese Parameter eingebaut, die sich nicht bestechen lassen.
Um einen Mißbrauch der Dateiformulare auszuschließen, wurde gefordert (und
das wurde von den Browserherstellern auch eingehalten), daß es keine Möglichkeit
geben soll, die Dateifelder vorzubelegen. Zum Vergleich: ein "normales"
Eingabefeld können Sie mit <input type="text" name="Vorbelegung" size="30" maxlength="30" value="Vorbelegung">. Auch Umwege über JavaScript sind nicht möglich, wie z.B. das Feld zuerst als Texteingabefeld zu deklarieren und vorzubelegen, und mit dem onLoad-Event der Datei den Typ von text in file zu
ändern und anschließend das Formular durch Aufrufen der Methode submit zu
versenden.
Das folgende Beispiel empfängt den gesendeten HTTP-Stream und wertet Ihn aus.
<html>
<head>
<title>Dateiupload per ASP</title>
</head>
<body bgcolor="white">
<%=Font%>
<%
' --- ASP FileUpload Modul GetFILE (C) 1999 by Stefan Falz
' --- Fehlerbehandlung aktivieren
' --- On Error Resume Next
' --- Zuweisen der Fehlerquelle, die bei einem Fehler ausgegeben werden soll
Err.Source = "GetFILE HTTP-Upload"
' --- Konstante für Fehlerüberschrift
Const ErrHeader = "<b>Fehler</b><br><br>"
' --- Array deklarieren
Dim ErrArray(4)
ErrArray(0) = "10900 - Ihre gesendete Datei ist zu groß."
ErrArray(1) = "10901 - Unbekannter Fehler.<br>"
ErrArray(2) = "10902 - Es wurde keine Datei gesendet oder die Übertragung ist fehlerhaft.<br>"
ErrArray(3) = "10903 - Es wurde keine Textdatei gesendet.<br>"
' -- Aufrufen der Subroutine GetFILE
Call GetFILE()
Private Sub GetFile()
' --- In dieser Subroutine wird der HTTP-Stream ausgelesen
' --- Deklarieren der Variablen
Dim FileText
FileText = Request.BinaryRead(Request.TotalBytes)
Dim FileTextByte
FileTextByte = ""
Dim FileTextNew
FileTextNew = ""
Dim FilePosFirst
FilePosFirst = 0
Dim FilePosLast
FilePosLast = 0
Dim FileType
FileType = ""
Dim strRevText
strRevText = ""
Dim strFileName
strFileName = ""
Dim strFileNameOnly
strFileName = ""
Dim posFileName
posFileName = 0
Dim rghFile
rghFileName = ""
Dim lenFileTextByte
lenFileTextByte = 0
' --- Angeben der max. Dateigröße + ca. 500 Byte für Dateiinformationen
Dim maxLength
maxLength = 25500
' --- Abfrage der Größe des gesendeten Streams
If Request.TotalBytes > maxLength Then
Call Error_Handler(10900)
Exit Sub
End if
' --- Suchen nach HexCode 0D 0A 0D 0A (Dateianfang innerhalb des HTTP-Streams)
FilePosFirst = InStrB(FileText, (ChrB(13) & ChrB(10) & ChrB(13) & ChrB(10)))
' --- Suchen nach HexCode 0D 0A 2D 2D (Dateiende innerhalb des HTTP-Streams)
FilePosLast = InStrB(FileText, (ChrB(13) & ChrB(10) & ChrB(45) & ChrB(45)))
' --- Suchen nach HexCode 2D 0A 0D innerhalb des umgedrehten HTTP-Streams, da unter
' --- Umständen mehrere Dateiendekennzeichen vorhanden sind.
strRevText = StrReverse(FileText)
FilePosLast = InStrB(strRevText, (ChrB(45) & ChrB(10)) & ChrB(13))
FilePosLast = LenB(FileText) - FilePosLast
' --- Abbruch bei Dateigröße 0 Byte
If FilePosFirst = 0 Or FilePosLast = 0 Or FilePosLast - FilePosFirst < 5 Then
Call Error_Handler(10902)
Exit Sub
End If
' --- Abbruch bei fehlender Angabe "Content-Disposition"
If InStrB(FileText, ChrB(67) & ChrB(111) & ChrB(110) & ChrB(116) & ChrB(101) & ChrB(110) & ChrB(116) & ChrB(45) & ChrB(84) & ChrB(121) & ChrB(112) & ChrB(101) & ChrB(58) & ChrB(32) & ChrB(116) & ChrB(101) & ChrB(120) & ChrB(116) & ChrB(47)) = 0 Then
Call Error_Handler(10903)
Exit Sub
End if
' --- Abbruch, wenn ein Fehler aufgetreten ist, der nicht zu den obigen Fehlern gehört
If Err.Number <> 0 Then
Call Error_Handler(10901)
Exit Sub
End if
' --- Ermittlung des Dateinamens inkl. Pfad innerhalb des HTTP-Streams
posFileName = InStrB(FileText, ChrB(102) & ChrB(105) & ChrB(108) & ChrB(101) & ChrB(110) & ChrB(97) & ChrB(109) & ChrB(101) & ChrB(61) & ChrB(34)) + 9
rghFileText = RightB(FileText, LenB(FileText) - posFileName)
strFileName = LeftB(rghFileText, InStrB(rghFileText, ChrB(34)) - 1)
Response.Write "<strong>Dateiname inkl. Pfad: </strong>"
Response.BinaryWrite strFileName
Response.Write "<br>"
' --- Ermittlung des Dateinamens exkl. Pfad innerhalb des HTTP-Streams
posLastSlash = InStrB(StrReverse(strFileName), ChrB(92))
strFileNameOnly = MidB(strFileName, LenB(strFileName) - posLastSlash, posLastSlash + 1)
Response.Write "<strong>Dateiname exkl. Pfad: </strong>"
Response.BinaryWrite strFileNameOnly
Response.Write "<br>"
' --- Abbruch, wenn ein Fehler aufgetrten ist
If Err <> 0 Then
Call Error_Handler(10901)
Exit Sub
End if
' --- Schreiben des Dateiinhalts in ByteArray
FileTextByte = MidB(FileText, (FilePosFirst + 4), (FilePosLast - (FilePosFirst + 4)))
' --- Ermittlung der Dateigröße durch Auslesen der Länge des ermittelten Dateiinhalts
lenFileTextByte = LenB(FileTextByte)
' --- Konvertierung des Dateiinhalts (Binärstream) in Ascii-Zeichen
For i = 1 To lenFileTextByte
FileTextNew = FileTextNew & Chr(AscB(MidB(FileTextByte, i, 1)))
Next
' --- Schreiben des ermittelten Dateiinhalts in eine Datei.
Set objFileSys = Server.CreateObject("Scripting.FileSystemObject")
Set File = objFileSys.CreateTextFile(Server.MapPath("./") & "\" & Session.SessionID & ".tmp", True, False)
File.WriteLine CStr(FileTextNew)
File.Close
Set File = Nothing
Set objFileSys = Nothing
' --- Ausgeben der Dateigröße in Bytes
Response.Write "<strong>Dateigröße: </strong>" & lenFileTextByte & " Byte.<br><br>"
' --- Konvertieren des Dateiinhalts, da HTML-Seiten nicht korrekt angezeigt werden
FileTextNew = Replace(FileTextNew, "<", "<")
FileTextNew = Replace(FileTextNew, ">", ">")
FileTextNew = Replace(FileTextNew, VbCrLf, "<br>" & VbCrLf)
FileTextNew = Replace(FileTextNew, Chr(9), " ")
' --- Ausgabe des Dateiinhalts
Response.Write FileTextNew
End Sub
Private Sub Error_Handler(intErrNumber)
' --- Ermitteln des übergebenen Fehlercodes und Ausgabe am Bildschirm
Select Case intErrNumber
Case 10900: Response.Write ErrHeader & ErrArray(0)
Case 10901: Response.Write ErrHeader & ErrArray(1)
Case 10902: Response.Write ErrHeader & ErrArray(2)
Case 10903: Response.Write ErrHeader & ErrArray(3)
Case Else: Response.Write ErrHeader & Err.Description
End Select
Exit Sub
End Sub
%>
</body>
</html>