02
2019
08

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+1, 1)))


i = 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))


%>

« 上一篇下一篇 »