[轉]ASP模拟POST提交请求上传文件

ASP模拟POST提交请求,可以支持文件上传的multipart/form-data表单方式。其实就是熟悉HTTP协议,构造请求头部,原理清晰,关键是细节的构造过程,可以举一反三,推广到其他语言中去。这是相当经典的代码,好好搜藏吧,哈哈!

发送端,构造头部脚本:


<%

Public Const adTypeBinary = 1

Public Const adTypeText = 2

Public Const adLongVarBinary = 205

'字节数组转指定字符集的字符串

Public Function BytesToString(vtData, ByVal strCharset)

    
Dim objFile

    
Set objFile = Server.CreateObject("ADODB.Stream")

    objFile.Type = adTypeBinary

    objFile.Open

    
If VarType(vtData) = vbString Then

        objFile.Write BinaryToBytes(vtData)

    
Else

        objFile.Write vtData

    
End If

    objFile.Position = 0

    objFile.Type = adTypeText

    objFile.Charset = strCharset

    BytesToString = objFile.ReadText(-1)

    objFile.Close

    
Set objFile = Nothing

End Function

'字节字符串转字节数组,即经过MidB/LeftB/RightB/ChrB等处理过的字符串

Public Function BinaryToBytes(vtData)

    
Dim rs

    
Dim lSize

    lSize = LenB(vtData)

    
Set rs = Server.CreateObject("ADODB.RecordSet")

    rs.Fields.Append "Content", adLongVarBinary, lSize

    rs.Open

    rs.AddNew

    rs("Content").AppendChunk vtData

    rs.Update

    BinaryToBytes = rs("Content").GetChunk(lSize)

    rs.Close

    
Set rs = Nothing

End Function

'指定字符集的字符串转字节数组

Public Function StringToBytes(ByVal strData, ByVal strCharset)

    
Dim objFile

    
Set objFile = Server.CreateObject("ADODB.Stream")

    objFile.Type = adTypeText

    objFile.Charset = strCharset

    objFile.Open

    objFile.WriteText strData

    objFile.Position = 0

    objFile.Type = adTypeBinary

    
If UCase(strCharset) = "UNICODE" Then

        objFile.Position = 2 'delete UNICODE BOM

    
ElseIf UCase(strCharset) = "UTF-8" Then

        objFile.Position = 3 'delete UTF-8 BOM

    
End If

    StringToBytes = objFile.Read(-1)

    objFile.Close

    
Set objFile = Nothing

End Function

'获取文件内容的字节数组

Public Function GetFileBinary(ByVal strPath)

    
Dim objFile

    
Set objFile = Server.CreateObject("ADODB.Stream")

    objFile.Type = adTypeBinary

    objFile.Open

    objFile.LoadFromFile strPath

    GetFileBinary = objFile.Read(-1)

    objFile.Close

    
Set objFile = Nothing

End Function

'XML Upload Class

Class XMLUploadImpl

Private xmlHttp

Private objTemp

Private strCharset, strBoundary

Private Sub Class_Initialize()

    
Set xmlHttp = Server.CreateObject("MSXML2.ServerXMLHTTP")

    
Set objTemp = Server.CreateObject("ADODB.Stream")

    objTemp.Type = adTypeBinary

    objTemp.Open

    strCharset = "GBK"

    strBoundary = GetBoundary()

End Sub

Private Sub Class_Terminate()

    objTemp.Close

    
Set objTemp = Nothing

    
Set xmlHttp = Nothing

End Sub

'获取自定义的表单数据分界线

Private Function GetBoundary()

    
Dim ret(24)

    
Dim table

    
Dim i

    table = "ABCDEFGHIJKLMNOPQRSTUVWXZYabcdefghijklmnopqrstuvwxzy0123456789"

    
Randomize

    
For i = 0 To UBound(ret)

        ret(i) = Mid(table, Int(Rnd() * Len(table) + 1), 1)

    
Next

    GetBoundary = "__NextPart__ " & Join(ret, Empty)

End Function 

 

Public Function Upload(ByVal strURL,ByVal cookiename,ByVal cookiecontent)   '改进之后可以输出cookie  session登录,哈哈

    
Call AddEnd

    xmlHttp.Open "POST", strURL, False

    
if cookiename<>"" and cookiecontent<>"" then

       xmlHttp.setRequestHeader "Cookie",cookiename&"="&cookiecontent&"; path=/; "    '登录的cookie信息,以后可以用用户名 密码来尝试读取登录信息

    
end if

       xmlHttp.setRequestHeader "User-Agent""User-Agent: Mozilla/4.0 (compatible; OpenOffice.org)"     '伪装浏览器

       xmlHttp.setRequestHeader "Connection""Keep-Alive"

    xmlHttp.setRequestHeader "Content-Type""multipart/form-data; boundary="&strBoundary               'PHP的问题就出在这里,没有指定分隔符号,自己不会分析读取,哈哈!搞定

    xmlHttp.setRequestHeader "Content-Length", objTemp.size

    xmlHttp.Send objTemp

        
If VarType(xmlHttp.responseBody) = (vbByte Or vbArray) Then 

            Upload = BytesToString(xmlHttp.responseBody, strCharset) 

        
End If

End Function

Public Function GetResponse()

    GetResponse=xmlHttp.getResponseHeader("Set-Cookie")       'getAllResponseHeaders("Set-Cookie") 获取cookie字符串

End Function

 

'设置上传使用的字符集

Public Property Let Charset(ByVal strValue)

    strCharset = strValue

End Property

'添加文本域的名称和值

Public Sub AddForm(ByVal strName, ByVal strValue)

    
Dim tmp

    tmp = "\r\n--$1\r\nContent-Disposition: form-data; name=""$2""\r\n\r\n$3"

    tmp = Replace(tmp, "\r\n", vbCrLf)

    tmp = Replace(tmp, "$1", strBoundary)

    tmp = Replace(tmp, "$2", strName)

    tmp = Replace(tmp, "$3", strValue)

    objTemp.Write StringToBytes(tmp, strCharset)

End Sub

'设置文件域的名称/文件名称/文件MIME类型/文件路径或文件字节数组

Public Sub AddFile(ByVal strName, ByVal strFileName, ByVal strFileType, vtValue)

    
Dim tmp

    tmp = "\r\n--$1\r\nContent-Disposition: form-data; name=""$2""; filename=""$3""\r\nContent-Type: $4\r\n\r\n"

    tmp = Replace(tmp, "\r\n", vbCrLf)

    tmp = Replace(tmp, "$1", strBoundary)

    tmp = Replace(tmp, "$2", strName)

    tmp = Replace(tmp, "$3", strFileName)

    tmp = Replace(tmp, "$4", strFileType)

    objTemp.Write StringToBytes(tmp, strCharset)

    
If VarType(vtValue) = (vbByte Or vbArray) Then

        objTemp.Write vtValue

    
Else

        objTemp.Write GetFileBinary(vtValue)

    
End If

End Sub

'设置multipart/form-data结束标记

Private Sub AddEnd()

    
Dim tmp

    
'tmp = Replace("\r\n--$1--\r\n", "$1", strBoundary)

        tmp = "\r\n--$1--\r\n" 

        tmp = Replace(tmp, "\r\n", vbCrLf) 

        tmp = Replace(tmp, "$1", strBoundary)

    objTemp.Write StringToBytes(tmp, strCharset)

    objTemp.Position = 2

End Sub

'上传到指定的URL,并返回服务器应答

Public Function Upload(ByVal strURL)

    
Call AddEnd

    xmlHttp.Open "POST", strURL, False

    xmlHttp.setRequestHeader "Content-Type""multipart/form-data"

    xmlHttp.setRequestHeader "Content-Length", objTemp.size

    xmlHttp.Send objTemp

        
If VarType(xmlHttp.responseBody) = (vbByte Or vbArray) Then 

            Upload = BytesToString(xmlHttp.responseBody, strCharset) 

        
End If

End Function

End Class

%>


<%

'在包含该文件后用以下代码调用 

'VB code

Dim UploadData

Set UploadData = New XMLUploadImpl

UploadData.Charset = "gb2312"

UploadData.AddForm "Test""123456" '文本域的名称和内容

'UploadData.AddFile "ImgFile", "F:\test.jpg", "image/jpg", GetFileBinary("F:\test.jpg")'图片或者其它文件

UploadData.AddFile "ImgFile", Server.MapPath("test.jpg"), "image/jpg", GetFileBinary(Server.MapPath("test.jpg"))'图片或者其它文件

Response.Write UploadData.Upload("http://localhost/receive.asp"'receive.asp为接收页面

Set UploadData = Nothing

%>

接收端,剥离读取头部字段:

<meta http-equiv="Content-Type" content="text/html; charset=GB2312" />


<%

Sub BuildUploadRequest(RequestBin)

    
'Get the boundary

    PosBeg = 1

    PosEnd = InstrB(PosBeg,RequestBin,getByteString(chr(13)))

    boundary = MidB(RequestBin,PosBeg,PosEnd-PosBeg)

    boundaryPos = InstrB(1,RequestBin,boundary)

    

    

    

    
'Get all data inside the boundaries

    
Do until (boundaryPos=InstrB(RequestBin,boundary & getByteString("--")))

        
'Members variable of objects are put in a dictionary object

        
Dim UploadControl

        
Set UploadControl = CreateObject("Scripting.Dictionary")

        

        
'Get an object name

        Pos = InstrB(BoundaryPos,RequestBin,getByteString("Content-Disposition"))

        Pos = InstrB(Pos,RequestBin,getByteString("name="))

        PosBeg = Pos+6

        PosEnd = InstrB(PosBeg,RequestBin,getByteString(chr(34)))    

        Name = getString(MidB(RequestBin,PosBeg,PosEnd-PosBeg))

        PosFile = InstrB(BoundaryPos,RequestBin,getByteString("filename="))

        PosBound = InstrB(PosEnd,RequestBin,boundary)

        

        
'Test if object is of file type

        
If  PosFile<>0 AND (PosFile<PosBound) Then

            

            
'Get Filename, content-type and content of file

            PosBeg = PosFile + 10

            PosEnd =  InstrB(PosBeg,RequestBin,getByteString(chr(34)))

            FileName = getString(MidB(RequestBin,PosBeg,PosEnd-PosBeg))

            

            

            
'Add filename to dictionary object

            UploadControl.Add "FileName", FileName

            Pos = InstrB(PosEnd,RequestBin,getByteString("Content-Type:"))

            PosBeg = Pos+14

            PosEnd = InstrB(PosBeg,RequestBin,getByteString(chr(13)))     

            

            

            
'Add content-type to dictionary object

            ContentType = getString(MidB(RequestBin,PosBeg,PosEnd-PosBeg))

            UploadControl.Add "ContentType",ContentType

            

            

            
'Get content of object

            PosBeg = PosEnd+4

            PosEnd = InstrB(PosBeg,RequestBin,boundary)-2

            Value = MidB(RequestBin,PosBeg,PosEnd-PosBeg)

            
Else

            

            
'Get content of object

            Pos = InstrB(Pos,RequestBin,getByteString(chr(13)))

            PosBeg = Pos+4

            PosEnd = InstrB(PosBeg,RequestBin,boundary)-2

            Value = getString(MidB(RequestBin,PosBeg,PosEnd-PosBeg))

        
End If

        

        
'Add content to dictionary object

    UploadControl.Add "Value" , Value    

        

        
'Add dictionary object to main dictionary

    UploadRequest.Add name, UploadControl    

        

        
'Loop to next object

        BoundaryPos=InstrB(BoundaryPos+LenB(boundary),RequestBin,boundary)

    
Loop

    

End Sub

<!--webbot bot="PurpleText" PREVIEW="end of建立上传数据字典的函数" -->

'String to byte string conversion

Function getByteString(StringStr)

For i = 1 to Len(StringStr)

     char = Mid(StringStr,i,1)

    getByteString = getByteString & chrB(AscB(char))

Next

End Function

'Byte string to string conversion(hoho,this can deal with chinese!!!)

Function getString(str)

strto = ""

for i=1 to lenb(str)

if AscB(MidB(str, i, 1)) > 127 then

strto = strto & chr(Ascb(MidB(str, i, 1))*256+Ascb(MidB(str, i+11)))

= i + 1

else

strto = strto & Chr(AscB(MidB(str, i, 1)))

end if

next

getString=strto

End Function

Function getStringold(StringBin)

getString =""

For intCount = 1 to LenB(StringBin)

    getString = getString & chr(AscB(MidB(StringBin,intCount,1))) 

Next

End Function

 

<!--webbot bot="PurpleText" PREVIEW="开始添加到数据库中去" -->

Response.Buffer = TRUE

Response.Clear

byteCount = Request.TotalBytes

'获得字节数

RequestBin = Request.BinaryRead(byteCount)

Dim UploadRequest

Set UploadRequest = CreateObject("Scripting.Dictionary")

BuildUploadRequest  RequestBin

filepath
= UploadRequest.Item("ImgFile").Item("FileName")   '获取上传文件的完整目录名字

compoundpic 
= UploadRequest.Item("ImgFile").Item("Value")

response.write(filepath
&" size:"&len(compoundpic))

%
>
posted @ 2009-09-29 12:34  Athrun  阅读(1262)  评论(0编辑  收藏  举报