Rev 29 | Blame | Compare with Previous | Last modification | View Log | RSS feed
<!--METADATATYPE="TypeLib"NAME="Microsoft ActiveX Data Objects 2.5 Library"UUID="{00000205-0000-0010-8000-00AA006D2EA4}"VERSION="2.5"--><!--#INCLUDE FILE="clsField.asp"--><%' ------------------------------------------------------------------------------' Author: Lewis Moten' Email: Lewis@Moten.com' URL: http://www.lewismoten.com' Date: March 19, 2002' ------------------------------------------------------------------------------' Upload class retrieves multi-part form data posted to web page' and parses it into objects that are easy to interface with.' Requires MDAC (ADODB) COM components found on most servers today' Additional compenents are not necessary.'' Demo:' Set objUpload = new clsUpload' Initializes object and parses all posted multi-part from data.' Once this as been done, Access to the Request object is restricted'' objUpload.Count' Number of fields retrieved'' use: Response.Write "There are " & objUpload.Count & " fields."'' objUpload.Fields' Access to field objects. This is the default propert so it does' not necessarily have to be specified. You can also determine if' you wish to specify the field index, or the field name.'' Use:' Set objField = objUpload.Fields("File1")' Set objField = objUpload("File1")' Set objField = objUpload.Fields(0)' Set objField = objUpload(0)' Response.Write objUpload("File1").Name' Response.Write objUpload(0).Name'' ------------------------------------------------------------------------------'' List of all fields passed:'' For i = 0 To objUpload.Count - 1' Response.Write objUpload(i).Name & "<BR>"' Next'' ------------------------------------------------------------------------------'' HTML needed to post multipart/form-data''<FORM method="post" encType="multipart/form-data" action="Upload.asp">' <INPUT type="File" name="File1">' <INPUT type="Submit" value="Upload">'</FORM>Class clsUpload' ------------------------------------------------------------------------------Private mbinData ' bytes visitor sent to serverPrivate mlngChunkIndex ' byte where next chunk startsPrivate mlngBytesReceived ' length of dataPrivate mstrDelimiter ' Delimiter between multipart/form-data (43 chars)Private CR ' ANSI Carriage ReturnPrivate LF ' ANSI Line FeedPrivate CRLF ' ANSI Carriage Return & Line FeedPrivate mobjFieldAry() ' Array to hold field objectsPrivate mlngCount ' Number of fields parsed' ------------------------------------------------------------------------------Private Sub RequestDataDim llngLength ' Number of bytes received' Determine number bytes visitor sentmlngBytesReceived = Request.TotalBytes' Store bytes recieved from visitormbinData = Request.BinaryRead(mlngBytesReceived)End Sub' ------------------------------------------------------------------------------Private Sub ParseDelimiter()' Delimiter seperates multiple pieces of form data' "around" 43 characters in length' next character afterwards is carriage return (except last line has two --)' first part of delmiter is dashes followed by hex number' hex number is possibly the browsers session id?' Examples:' -----------------------------7d230d1f940246' -----------------------------7d22ee291ae0114mstrDelimiter = MidB(mbinData, 1, InStrB(1, mbinData, CRLF) - 1)End Sub' ------------------------------------------------------------------------------Private Sub ParseData()' This procedure loops through each section (chunk) found within the' delimiters and sends them to the parse chunk routineDim llngStart ' start position of chunk dataDim llngLength ' Length of chunkDim llngEnd ' Last position of chunk dataDim lbinChunk ' Binary contents of chunk' Initialize at first characterllngStart = 1' Find start positionllngStart = InStrB(llngStart, mbinData, mstrDelimiter & CRLF)' While the start posotion was foundWhile Not llngStart = 0' Find the end position (after the start position)llngEnd = InStrB(llngStart + 1, mbinData, mstrDelimiter) - 2' Determine Length of chunkllngLength = llngEnd - llngStart' Pull out the chunklbinChunk = MidB(mbinData, llngStart, llngLength)' Parse the chunkCall ParseChunk(lbinChunk)' Look for next chunk after the start positionllngStart = InStrB(llngStart + 1, mbinData, mstrDelimiter & CRLF)WendEnd Sub' ------------------------------------------------------------------------------Private Sub ParseChunk(ByRef pbinChunk)' This procedure gets a chunk passed to it and parses its contents.' There is a general format that the chunk follows.' First, the deliminator appears' Next, headers are listed on each line that define properties of the chunk.' Content-Disposition: form-data: name="File1"; filename="C:\Photo.gif"' Content-Type: image/gif' After this, a blank line appears and is followed by the binary data.Dim lstrName ' Name of fieldDim lstrFileName ' File name of binary dataDim lstrContentType ' Content type of binary dataDim lbinData ' Binary dataDim lstrDisposition ' Content DispositionDim lstrValue ' Value of field' Parse out the content dispostionlstrDisposition = ParseDisposition(pbinChunk)' And Parse the NamelstrName = ParseName(lstrDisposition)' And the file namelstrFileName = ParseFileName(lstrDisposition)' Parse out the Content TypelstrContentType = ParseContentType(pbinChunk)' If the content type is not defined, then assume the' field is a normal form fieldIf lstrContentType = "" Then' Parse Binary Data as UnicodelstrValue = CStrU(ParseBinaryData(pbinChunk))' Else assume the field is binary dataElse' Parse Binary DatalbinData = ParseBinaryData(pbinChunk)End If' Add a new fieldCall AddField(lstrName, lstrFileName, lstrContentType, lstrValue, lbinData)End Sub' ------------------------------------------------------------------------------Private Sub AddField(ByRef pstrName, ByRef pstrFileName, ByRef pstrContentType, ByRef pstrValue, ByRef pbinData)Dim lobjField ' Field object class' Add a new index to the field array' Make certain not to destroy current fieldsReDim Preserve mobjFieldAry(mlngCount)' Create new field objectSet lobjField = New clsField' Set field propertieslobjField.Name = pstrNamelobjField.FilePath = pstrFileNamelobjField.ContentType = pstrContentType' If field is not a binary fileIf LenB(pbinData) = 0 ThenlobjField.BinaryData = ChrB(0)lobjField.Value = pstrValuelobjField.Length = Len(pstrValue)' Else field is a binary fileElselobjField.BinaryData = pbinDatalobjField.Length = LenB(pbinData)lobjField.Value = ""End If' Set field array index to new fieldSet mobjFieldAry(mlngCount) = lobjField' Incriment field countmlngCount = mlngCount + 1End Sub' ------------------------------------------------------------------------------Private Function ParseBinaryData(ByRef pbinChunk)' Parses binary content of the chunkDim llngStart ' Start Position' Find first occurence of a blank linellngStart = InStrB(1, pbinChunk, CRLF & CRLF)' If it doesn't exist, then return nothingIf llngStart = 0 Then Exit Function' Incriment start to pass carriage returns and line feedsllngStart = llngStart + 4' Return the last part of the chunk after the start positionParseBinaryData = MidB(pbinChunk, llngStart)End Function' ------------------------------------------------------------------------------Private Function ParseContentType(ByRef pbinChunk)' Parses the content type of a binary file.' example: image/gif is the content type of a GIF image.Dim llngStart ' Start PositionDim llngEnd ' End PositionDim llngLength ' Length' Fid the first occurance of a line starting with Content-Type:llngStart = InStrB(1, pbinChunk, CRLF & CStrB("Content-Type:"), vbTextCompare)' If not found, return nothingIf llngStart = 0 Then Exit Function' Find the end of the linellngEnd = InStrB(llngStart + 15, pbinChunk, CR)' If not found, return nothingIf llngEnd = 0 Then Exit Function' Adjust start position to start after the text "Content-Type:"llngStart = llngStart + 15' If the start position is the same or past the end, return nothingIf llngStart >= llngEnd Then Exit Function' Determine lengthllngLength = llngEnd - llngStart' Pull out content type' Convert to unicode' Trim out whitespace' Return resultsParseContentType = Trim(CStrU(MidB(pbinChunk, llngStart, llngLength)))End Function' ------------------------------------------------------------------------------Private Function ParseDisposition(ByRef pbinChunk)' Parses the content-disposition from a chunk of data'' Example:'' Content-Disposition: form-data: name="File1"; filename="C:\Photo.gif"'' Would Return:' form-data: name="File1"; filename="C:\Photo.gif"Dim llngStart ' Start PositionDim llngEnd ' End PositionDim llngLength ' Length' Find first occurance of a line starting with Content-Disposition:llngStart = InStrB(1, pbinChunk, CRLF & CStrB("Content-Disposition:"), vbTextCompare)' If not found, return nothingIf llngStart = 0 Then Exit Function' Find the end of the linellngEnd = InStrB(llngStart + 22, pbinChunk, CRLF)' If not found, return nothingIf llngEnd = 0 Then Exit Function' Adjust start position to start after the text "Content-Disposition:"llngStart = llngStart + 22' If the start position is the same or past the end, return nothingIf llngStart >= llngEnd Then Exit Function' Determine LengthllngLength = llngEnd - llngStart' Pull out content disposition' Convert to Unicode' Return ResultsParseDisposition = CStrU(MidB(pbinChunk, llngStart, llngLength))End Function' ------------------------------------------------------------------------------Private Function ParseName(ByRef pstrDisposition)' Parses the name of the field from the content disposition'' Example'' form-data: name="File1"; filename="C:\Photo.gif"'' Would Return:' File1Dim llngStart ' Start PositionDim llngEnd ' End PositionDim llngLength ' Length' Find first occurance of text name="llngStart = InStr(1, pstrDisposition, "name=""", vbTextCompare)' If not found, return nothingIf llngStart = 0 Then Exit Function' Find the closing quotellngEnd = InStr(llngStart + 6, pstrDisposition, """")' If not found, return nothingIf llngEnd = 0 Then Exit Function' Adjust start position to start after the text name="llngStart = llngStart + 6' If the start position is the same or past the end, return nothingIf llngStart >= llngEnd Then Exit Function' Determine LengthllngLength = llngEnd - llngStart' Pull out field name' Return resultsParseName = Mid(pstrDisposition, llngStart, llngLength)End Function' ------------------------------------------------------------------------------Private Function ParseFileName(ByRef pstrDisposition)' Parses the name of the field from the content disposition'' Example'' form-data: name="File1"; filename="C:\Photo.gif"'' Would Return:' C:\Photo.gifDim llngStart ' Start PositionDim llngEnd ' End PositionDim llngLength ' Length' Find first occurance of text filename="llngStart = InStr(1, pstrDisposition, "filename=""", vbTextCompare)' If not found, return nothingIf llngStart = 0 Then Exit Function' Find the closing quotellngEnd = InStr(llngStart + 10, pstrDisposition, """")' If not found, return nothingIf llngEnd = 0 Then Exit Function' Adjust start position to start after the text filename="llngStart = llngStart + 10' If the start position is the same of past the end, return nothingIf llngStart >= llngEnd Then Exit Function' Determine lengthllngLength = llngEnd - llngStart' Pull out file name' Return resultsParseFileName = Mid(pstrDisposition, llngStart, llngLength)End Function' ------------------------------------------------------------------------------Public Property Get Count()' Return number of fields foundCount = mlngCountEnd Property' ------------------------------------------------------------------------------Public Default Property Get Fields(ByVal pstrName)Dim llngIndex ' Index of current field' If a number was passedIf IsNumeric(pstrName) ThenllngIndex = CLng(pstrName)' If programmer requested an invalid numberIf llngIndex > mlngCount - 1 Or llngIndex < 0 Then' Raise an errorCall Err.Raise(vbObjectError + 1, "clsUpload.asp", "Object does not exist within the ordinal reference.")Exit PropertyEnd If' Return the field class for the index specifiedSet Fields = mobjFieldAry(pstrName)' Else a field name was passedElse' convert name to lowercasepstrName = LCase(pstrname)' Loop through each fieldFor llngIndex = 0 To mlngCount - 1' If name matches current fields name in lowercaseIf LCase(mobjFieldAry(llngIndex).Name) = pstrName Then' Return Field ClassSet Fields = mobjFieldAry(llngIndex)Exit PropertyEnd IfNextEnd If' If matches were not found, return an empty fieldSet Fields = New clsField' ' ERROR ON NonExistant:' ' If matches were not found, raise an error of a non-existent field' Call Err.Raise(vbObjectError + 1, "clsUpload.asp", "Object does not exist within the ordinal reference.")' Exit PropertyEnd Property' ------------------------------------------------------------------------------Private Sub Class_Terminate()' This event is called when you destroy the class.'' Example:' Set objUpload = Nothing'' Example:' Response.End'' Example:' Page finnishes executing ...Dim llngIndex ' Current Field Index' Loop through fieldsFor llngIndex = 0 To mlngCount - 1' Release field objectSet mobjFieldAry(llngIndex) = NothingNext' Redimension array and remove all data withinReDim mobjFieldAry(-1)End Sub' ------------------------------------------------------------------------------Private Sub Class_Initialize()' This event is called when you instantiate the class.'' Example:' Set objUpload = New clsUpload' Redimension array with nothingReDim mobjFieldAry(-1)' Compile ANSI equivilants of carriage returns and line feedsCR = ChrB(Asc(vbCr)) ' vbCr Carriage ReturnLF = ChrB(Asc(vbLf)) ' vbLf Line FeedCRLF = CR & LF ' vbCrLf Carriage Return & Line Feed' Set field count to zeromlngCount = 0' Request dataCall RequestData' Parse out the delimiterCall ParseDelimiter()' Parse the dataCall ParseDataEnd Sub' ------------------------------------------------------------------------------Private Function CStrU(ByRef pstrANSI)' Converts an ANSI string to Unicode' Best used for small stringsDim llngLength ' Length of ANSI stringDim llngIndex ' Current position' determine lengthllngLength = LenB(pstrANSI)' Loop through each characterFor llngIndex = 1 To llngLength' Pull out ANSI character' Get Ascii value of ANSI character' Get Unicode Character from Ascii' Append character to resultsCStrU = CStrU & Chr(AscB(MidB(pstrANSI, llngIndex, 1)))NextEnd Function' ------------------------------------------------------------------------------Private Function CStrB(ByRef pstrUnicode)' Converts a Unicode string to ANSI' Best used for small stringsDim llngLength ' Length of ANSI stringDim llngIndex ' Current position' determine lengthllngLength = Len(pstrUnicode)' Loop through each characterFor llngIndex = 1 To llngLength' Pull out Unicode character' Get Ascii value of Unicode character' Get ANSI Character from Ascii' Append character to resultsCStrB = CStrB & ChrB(Asc(Mid(pstrUnicode, llngIndex, 1)))NextEnd Function' ------------------------------------------------------------------------------End Class' ------------------------------------------------------------------------------%>