VB.Net Socket实现Http文件上传及下载类

摘要:
Wd=hello“httpClient.strTextField=”user=zhans&psd=1332“httpClient.Proc'true表示记录cookie MsgboxImportsSystemImportsSystem.IOImportsSystem.NetImportsSystem.Net.SocketsImportsMicrosoft.VisualBasic“”<summary>“”实现了向web发送和接收数据的类“”--HEDAODE--“ConstSEND_BUFFER_SIZEAsInteger=8000ConstRECEIVE_BUFFER_SIZEAsInteger=15000Dim_strUrl,_strTextField,_strFileFieldAsStringDimmethod,contentType,host,path,_headerText,_respHtml,_referer,_cookieAsStringPublicEncodeAsEncoding=编码.DefaultDimrAsRegularExpressions.RegexDimAsRegularExpression.MatchDimPostDataList(),header()AsByteDim_ startAsBoolean=TrueDim_ SendProgress,_ ReceiveProgress,_SendContentLength,_ ReceiveContentLength,startIndexAsInteger“”<summary>“”请求的url地址“”</summary>‘”<value></value>“’<return></returns>‘’<remarks></remarks>PropertystrUrl()AsStringGetReturn_ strUrlEndGetSetIfvalue<>“”Thenm=r.Match(value,“https://([^/]+)(/(.+))?

GET访问:

dim httpClient as new WebClient()
httpClient.strUrl="http://www.baidu/com?wd=hello"
httpClient.Proc()
Msgbox(httpClient.RespHtml)

POST访问:

dim httpClient as new WebClient()
httpClient.strUrl="http://www.baidu/com?wd=hello"
httpClient.strTextField="user=zhans&psd=1332"
httpClient.Proc(true)'true表示要记录cookie
Msgbox(httpClient.RespHtml)
Imports System
Imports System.Text
Imports System.IO
Imports System.Net
Imports System.Net.Sockets
Imports Microsoft.VisualBasic

''' <summary>
''' 实现向web发送和接收数据的类
''' </summary>
''' <remarks></remarks>
Public Class WebClient

    Const BOUNDARY As String = "--HEDAODE--"

    Const SEND_BUFFER_SIZE As Integer = 8000

    Const RECEIVE_BUFFER_SIZE As Integer = 15000

    Dim _strUrl, _strTextField, _strFileField As String

    Dim method, contentType, host, path, _headerText, _respHtml, _referer, _cookie As String

    Public Encode As Encoding = Encoding.Default

    Dim r As RegularExpressions.Regex

    Dim m As RegularExpressions.Match

    Dim PostDataList()(), header() As Byte

    Dim _start As Boolean = True

    Dim _SendProgress, _ReceiveProgress, _SendContentLength, _ReceiveContentLength, startIndex As Integer
   
    ''' <summary>
    ''' 请求的url地址
    ''' </summary>
    ''' <value></value>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Property strUrl() As String

        Get

            Return _strUrl

        End Get

        Set(ByVal value As String)

            If value <> "" Then

                m = r.Match(value, "https*://([^/]+)(/(.+))?")

                If m.Success Then

                    host = m.Groups(1).Value

                    path = "/" + m.Groups(3).Value

                    _strUrl = value

                Else

                    MsgBox("URL不合法!")

                End If

            End If

        End Set

    End Property

    ''' <summary>

    ''' 要发送的文本域

    ''' </summary>

    ''' <value></value>

    ''' <returns></returns>

    ''' <remarks></remarks>

    Property strTextField() As String

        Get

            Return _strTextField

        End Get

        Set(ByVal value As String)

            If value <> "" Then

                m = r.Match(value, "(\w+=[^&]+)|((\w+=[^&]+&)+)")

                If m.Success Then

                    _strTextField = value

                Else

                    MsgBox("数据有误:" & value)

                End If

            End If

        End Set

    End Property

    ''' <summary>

    ''' 要发送的文件域

    ''' </summary>

    ''' <value></value>

    ''' <returns></returns>

    ''' <remarks></remarks>

    Property strFileField() As String

        Get

            Return _strFileField

        End Get

        Set(ByVal value As String)

            If value <> "" Then

                m = r.Match(value, "(\w+=[^&]+)|((\w+=[^&]+&)+)")

                If m.Success Then

                    _strFileField = value

                Else

                    MsgBox("数据有误:" & value)

                End If

            End If

        End Set

    End Property

    ''' <summary>

    ''' 获取或设置Cookie

    ''' </summary>

    ''' <value></value>

    ''' <returns></returns>

    ''' <remarks>用来跟踪用户身份</remarks>

    Property Cookie() As String

        Get

            Return _cookie

        End Get

        Set(ByVal value As String)

            _cookie = value

        End Set

    End Property

    ''' <summary>

    ''' 获取或设置Referer

    ''' </summary>

    ''' <value></value>

    ''' <returns></returns>

    ''' <remarks>模拟上一次访问地址</remarks>

    Property Referer() As String

        Get

            Return _referer

        End Get

        Set(ByVal value As String)

            _referer = value

        End Set

    End Property

    ''' <summary>

    ''' 获取http响应头文本

    ''' </summary>

    ''' <value></value>

    ''' <returns></returns>

    ''' <remarks></remarks>

    ReadOnly Property headerText() As String

        Get

            Return _headerText

        End Get

    End Property

    ''' <summary>

    ''' 获取服务器返回的文本

    ''' </summary>

    ''' <value></value>

    ''' <returns></returns>

    ''' <remarks></remarks>

    Property RespHtml() As String

        Get

            Return _respHtml

        End Get

        Set(ByVal value As String)

            _respHtml = value

        End Set

    End Property

    ''' <summary>

    ''' 获取发送实体大小

    ''' </summary>

    ''' <value></value>

    ''' <returns></returns>

    ''' <remarks></remarks>

    ReadOnly Property SendContentLength() As Integer

        Get

            Return _SendContentLength

        End Get

    End Property

    ''' <summary>

    ''' 获取接收实体大小

    ''' </summary>

    ''' <value></value>

    ''' <returns></returns>

    ''' <remarks></remarks>

    ReadOnly Property ReceiveContentLength() As Integer

        Get

            Return _ReceiveContentLength

        End Get

    End Property

    ''' <summary>

    ''' 获取数据发送进度

    ''' </summary>

    ''' <value></value>

    ''' <returns></returns>

    ''' <remarks></remarks>

    ReadOnly Property SendProgress() As Integer

        Get

            Return _SendProgress

        End Get

    End Property

    ''' <summary>

    ''' 获取数据接收进度

    ''' </summary>

    ''' <value></value>

    ''' <returns></returns>

    ''' <remarks></remarks>

    ReadOnly Property ReceiveProgress() As Integer

        Get

            Return _ReceiveProgress

        End Get

    End Property

    ''' <summary>

    ''' 设置是否立即中断发送和接收数据

    ''' </summary>

    ''' <value></value>

    ''' <returns></returns>

    ''' <remarks></remarks>

    Property Start() As Boolean

        Get

            Return _start

        End Get

        Set(ByVal value As Boolean)

            _start = value

        End Set

    End Property

    ''' <summary>

    ''' 建立socket连接

    ''' </summary>

    ''' <param name="server"></param>

    ''' <param name="port"></param>

    ''' <returns></returns>

    ''' <remarks></remarks>

    Private Function ConnectSocket(ByVal server As String, ByVal port As Integer) As Sockets.Socket

        Dim s As Sockets.Socket = Nothing

        Dim hostEntry As IPHostEntry = Nothing

        ' Get host related information.

        Try

            hostEntry = Dns.GetHostEntry(server)

            ' Loop through the AddressList to obtain the supported AddressFamily. This is to avoid

            ' an exception that occurs when the host host IP Address is not compatible with the address family

            ' (typical in the IPv6 case).

            Dim address As IPAddress

            For Each address In hostEntry.AddressList

                Dim endPoint As New IPEndPoint(address, port)

                Dim tempSocket As New Sockets.Socket(endPoint.AddressFamily, SocketType.Stream, ProtocolType.Tcp)

                tempSocket.Connect(endPoint)

                If tempSocket.Connected Then

                    s = tempSocket

                    Exit For

                End If

            Next address

            Return s

        Catch ex As Exception

            Return Nothing

        End Try

    End Function

    ''' <summary>

    ''' 发送并接收数据

    ''' </summary>

    ''' <returns></returns>

    ''' <remarks></remarks>

    Private Function SocketSendReceive(Optional ByVal progress As Boolean = False) As Byte()

        _SendProgress = 0

        _ReceiveProgress = 0

        Dim s As Sockets.Socket = ConnectSocket(host, 80)

        If s Is Nothing Then

            Return Encode.GetBytes("无法解析主机名称")

        End If

        Dim i, count As Integer

        Dim receivedByte() As Byte

        '创建请求数据

        CreateRequestData()

        Try

            '发送数据****************************************

            s.SendTimeout = 5000

            s.Send(header) '发送请求头

            '如果有数据要发送就继续发送

            If Me._SendContentLength > 0 Then

                For i = 0 To PostDataList.Length - 1

                    If Not Start Then

                        s.Close()

                        Return Encode.GetBytes("中断")

                    End If

                    s.Send(PostDataList(i)) '将缓冲区的数据发送出去

                    _SendProgress += PostDataList(i).Length

                Next

                s.Shutdown(SocketShutdown.Send) '停止发送数据

            End If

            '接收数据*****************************************

            Do

                If Not Start Then

                    s.Close()

                    Return Encode.GetBytes("中断")

                End If

                Dim receiveBuffer(RECEIVE_BUFFER_SIZE) As Byte

                count = s.Receive(receiveBuffer)

                ReDim Preserve receiveBuffer(count - 1)

                receivedByte = UniteArr(receivedByte, receiveBuffer)

                _ReceiveProgress += count

            Loop While count > 0

            s.Close()

            Me._strTextField = ""

            Me._strFileField = ""

            Return GetResponseByte(receivedByte)

        Catch ex As Exception

            Return Encode.GetBytes(ex.Message)

        End Try

    End Function

    ''' <summary>

    ''' 分析服务器返回的字节流,去掉响应头,返回实体部分

    ''' </summary>

    ''' <param name="receivedByte"></param>

    ''' <returns></returns>

    ''' <remarks></remarks>

    Function GetResponseByte(ByRef receivedByte() As Byte) As Byte()

        Dim tempByte() As Byte

        If Not receivedByte Is Nothing Then

            If receivedByte.Length <= 5000 Then

                GetHeaderInfo(receivedByte)

            Else

                Dim headByte(5000) As Byte

                Array.Copy(receivedByte, headByte, 5000)

                GetHeaderInfo(headByte)

            End If

            If Me._ReceiveContentLength > receivedByte.Length - startIndex Then

                ReDim tempByte(receivedByte.Length - startIndex - 1)

                Me._ReceiveContentLength = tempByte.Length

                Array.Copy(receivedByte, startIndex, tempByte, 0, tempByte.Length)

            Else

                ReDim tempByte(Me._ReceiveContentLength - 1)

                Array.Copy(receivedByte, startIndex, tempByte, 0, Me._ReceiveContentLength)

            End If

            Return tempByte

        Else

            Return Encode.GetBytes("没有数据返回")

        End If

    End Function

    ''' <summary>

    ''' 分析获取响应头,获取实体大小

    ''' </summary>

    ''' <param name="receiveBuffer"></param>

    ''' <remarks></remarks>

    Private Sub GetHeaderInfo(ByVal receiveBuffer() As Byte)

        Dim text As String = Encode.GetChars(receiveBuffer)

        m = r.Match(text, "(.+" + vbCrLf + ")+" + vbCrLf + "((?<len>[a-fA-F0-9]{1,20}) {0,20}" + vbCrLf + ")?")

        If m.Success Then

            If m.Groups("len").Value <> "" Then

                '某些服务器在响应头里

                Me._ReceiveContentLength = "&H" + m.Groups("len").Value

            Else

                Me._ReceiveContentLength = 500000 '如果响应头中没有实体大小,就取前500K,但这种几率很小

            End If

            startIndex = Encode.GetBytes((m.Value)).Length '实体开始的字节位置

            _headerText = m.Value '响应头

        End If

        '获取实体大小

        m = r.Match(text, "Content-Length:(?<len>.+)")

        If m.Success Then

            Me._ReceiveContentLength = Trim(m.Groups("len").Value)

        End If

    End Sub

    ''' <summary>

    ''' 向服务器请求数据并返回响应文本

    ''' </summary>

    ''' <param name="SetCookie">如果要保存cookie则为true</param>

    ''' <returns></returns>

    ''' <remarks></remarks>

    Function Proc(Optional ByVal SetCookie As Boolean = False) As String

        _respHtml = Encode.GetChars(SocketSendReceive)

        If SetCookie And _headerText <> "" Then

            '从响应头中获取cookie

            m = r.Match(_headerText, "Set-Cookie:([^;]+)")

            Do While m.Success

                Cookie += m.Groups(1).Value + ";"

                m = m.NextMatch

            Loop

            Cookie = Trim(Cookie)

        End If

        Return _respHtml

    End Function

    ''' <summary>

    ''' 上传文件

    ''' </summary>

    ''' <returns></returns>

    ''' <remarks></remarks>

    Function UploadFile() As String

        _respHtml = Encode.GetChars(SocketSendReceive)

        Return _respHtml

    End Function

    ''' <summary>

    ''' 下载文件

    ''' </summary>

    ''' <param name="SavePath">文件保存路径,含文件名</param>

    ''' <remarks></remarks>

    Sub DownLoadFile(ByVal SavePath As String)

        Dim receivedData() As Byte = SocketSendReceive()

        If Start Then

            Dim fs As New FileStream(SavePath, FileMode.Create)

            fs.Write(receivedData, 0, receivedData.Length)

            fs.Close()

            fs = Nothing

        End If

    End Sub

    ''' <summary>

    ''' 创建http请求数据包

    ''' </summary>

    ''' <remarks></remarks>

    Private Sub CreateRequestData()

        Dim PostData() As Byte

        If strTextField = "" And strFileField = "" Then

            '不发送任何数据

            Me.method = "GET"

            Me._SendContentLength = 0

        ElseIf strTextField <> "" And strFileField <> "" Then

            '发送文本和文件数据

            Dim strText As String = ""

            m = r.Match(_strTextField, "(\w+)=([^&]+)")

            Do While m.Success

                strText += "--" + BOUNDARY + vbCrLf

                strText += "Content-Disposition: form-data; name=""" + m.Groups(1).Value + """" + vbCrLf + vbCrLf + m.Groups(2).Value + vbCrLf

                m = m.NextMatch

            Loop

            PostData = UniteArr(Encode.GetBytes(strText), GetFileByte(_strFileField))

            Me.method = "POST"

            Me.contentType = "multipart/form-data; boundary=" + BOUNDARY

            Me._SendContentLength = PostData.Length

            GetPostDataList(PostData)

        ElseIf strTextField <> "" Then

            '只发送文本数据

            PostData = Encode.GetBytes(strTextField)

            Me.method = "POST"

            Me.contentType = "application/x-www-form-urlencoded"

            Me._SendContentLength = PostData.Length

            GetPostDataList(PostData)

        ElseIf strFileField <> "" Then

            '只发送文件数据

            PostData = GetFileByte(strFileField)

            Me.method = "POST"

            Me.contentType = "multipart/form-data; boundary=" + BOUNDARY

            Me._SendContentLength = PostData.Length

            GetPostDataList(PostData)

        End If

        header = GetHeader()

    End Sub

    ''' <summary>

    ''' 获取http请求头数据

    ''' </summary>

    ''' <returns></returns>

    ''' <remarks></remarks>

    Private Function GetHeader() As Byte()

        Dim strHeader As String

        strHeader = method + " " + path + " HTTP/1.1" + vbCrLf

        strHeader += "Accept: */*" + vbCrLf

        strHeader += "Accept-Language: zh-cn" + vbCrLf

        strHeader += "User-Agent: Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.2; SV1; .NET CLR 1.1.4322; .NET CLR 2.0.50727)" + vbCrLf

        strHeader += "Host: " + host + vbCrLf

        If Referer <> "" Then

            strHeader += "Referer: " + Referer + vbCrLf

        End If

        Referer = ""

        If Me._SendContentLength > 0 Then

            strHeader += "Content-Type: " + contentType + vbCrLf

            strHeader += "Content-Length: " & Me._SendContentLength & vbCrLf

            'strHeader += "Expect:100-continue" + vbCrLf

            strHeader += "Connection: Keep-Alive" + vbCrLf

        Else

            strHeader += "Connection: Close" + vbCrLf

        End If

        If Cookie <> "" Then strHeader += "Cookie: " + _cookie + vbCrLf

        strHeader += vbCrLf

        Return Encode.GetBytes(strHeader)

    End Function

    ''' <summary>

    ''' 获取发送文件数据

    ''' </summary>

    ''' <param name="strFileField">文件域名称及文件路径</param>

    ''' <returns></returns>

    ''' <remarks></remarks>

    Private Function GetFileByte(ByVal strFileField As String) As Byte()

        Dim postByte() As Byte

        Dim filePath As String

        m = r.Match(strFileField, "(\w+)=([^&]+)")

        Do While m.Success

            filePath = m.Groups(2).Value

            If File.Exists(filePath) Then

                strFileField = "--" + BOUNDARY + vbCrLf

                strFileField += "Content-Disposition: form-data; name=""" + m.Groups(1).Value + """; filename=""" + filePath + """" + vbCrLf

                strFileField += "Content-Type: image/jpeg" + vbCrLf + vbCrLf

                postByte = UniteArr(postByte, Encode.GetBytes(strFileField))

                Dim fs As New FileStream(filePath, FileMode.Open)

                Dim br As New BinaryReader(fs)

                postByte = UniteArr(postByte, br.ReadBytes(fs.Length))

                br.Close()

                fs.Close()

                postByte = UniteArr(postByte, Encode.GetBytes(vbCrLf))

            Else

                MsgBox("上传文件不存在!")

            End If

            m = m.NextMatch

        Loop

        postByte = UniteArr(postByte, Encode.GetBytes("--" + BOUNDARY + "--" + vbCrLf))

        Return postByte

    End Function

    ''' <summary>

    ''' 将大数据包拆分成小包

    ''' </summary>

    ''' <param name="postData">要拆分的数据包</param>

    ''' <remarks></remarks>

    Private Sub GetPostDataList(ByRef postData() As Byte)

        Dim blockCount, remnant, i, p As Integer

        blockCount = postData.Length \ SEND_BUFFER_SIZE '整块个数

        remnant = postData.Length Mod SEND_BUFFER_SIZE '零头

        Dim bufferList(blockCount + IIf(remnant > 0, 0, -1))() As Byte

        '复制整块

        For i = 0 To blockCount - 1

            ReDim bufferList(i)(SEND_BUFFER_SIZE - 1)

            System.Array.Copy(postData, p, bufferList(i), 0, SEND_BUFFER_SIZE)

            p += SEND_BUFFER_SIZE

        Next

        '复制零头

        If remnant > 0 Then

            ReDim bufferList(i)(remnant - 1)

            System.Array.Copy(postData, p, bufferList(i), 0, remnant)

        End If

        PostDataList = bufferList

    End Sub

    ''' <summary>

    ''' 合并两个字节数组

    ''' </summary>

    ''' <param name="byte1"></param>

    ''' <param name="byte2"></param>

    ''' <returns></returns>

    ''' <remarks></remarks>

    Function UniteArr(ByVal byte1() As Byte, ByVal byte2() As Byte) As Byte()

        Dim temp() As Byte

        If byte1 Is Nothing And byte2 Is Nothing Then

            MsgBox("两个数组不能同时为空!")

            Return Nothing

        ElseIf byte1 Is Nothing Then

            ReDim temp(byte2.Length - 1)

            Array.Copy(byte2, 0, temp, 0, byte2.Length)

        ElseIf byte2 Is Nothing Then

            ReDim temp(byte1.Length - 1)

            Array.Copy(byte1, 0, temp, 0, byte1.Length)

        Else

            ReDim temp(byte1.Length + byte2.Length - 1)

            Array.Copy(byte1, 0, temp, 0, byte1.Length)

            Array.Copy(byte2, 0, temp, byte1.Length, byte2.Length)

        End If

        Return temp

    End Function

End Class

免责声明:文章转载自《VB.Net Socket实现Http文件上传及下载类》仅用于学习参考。如对内容有疑问,请及时联系本站处理。

上篇2)PHP中把读取.txt中内容并转为UTF-8格式PHP乱码问题,UTF-8乱码常见问题小结 linux-windows 文件编码乱码问题下篇

宿迁高防,2C2G15M,22元/月;香港BGP,2C5G5M,25元/月 雨云优惠码:MjYwNzM=

相关文章

Python解析Pcap包类源码学习

0x1、前言 ​ 在现场取证遇到分析流量包的情况会比较少,虽然流量类设备原理是把数据都抓出来进行解析,很大一定程度上已经把人可以做的事情交给了机器自动完成。 ​ 可用于PCAP包分析的软件比如科来,Wireshark都是很好用的分析软件,找Pcap解析的编程类代码时发现已经有很多大佬写过Python脚本辅助解析Pcap,也有提取将Pcap信息以界面形式展示...

Java:双括号初始化 /匿名内部类初始化法

偶然见到一种初始化方式,感到十分新奇: //新建一个列表并赋初值A、B、C ArrayList<String> list = new ArrayList<String>() {{ add("A"); add("B"); add("C"); }};...

高可用的Spring FTP上传下载工具类(已解决上传过程常见问题)

前言 最近在项目中需要和ftp服务器进行交互,在网上找了一下关于ftp上传下载的工具类,大致有两种。 第一种是单例模式的类。 第二种是另外定义一个Service,直接通过Service来实现ftp的上传下载删除。 这两种感觉都有利弊。 第一种实现了代码复用,但是配置信息全需要写在类中,维护比较复杂。 第二种如果是spring框架,可以通过propertis...

StringUtils类方法详解

org.apache.commons.lang.StringUtils中方法的操作对象是java.lang.String类型的对象,是JDK提供的String类型操作方法的补充,并且是null安全的(即如果输入参数String为null则不会抛出NullPointerException,而是做了相应处理,例如,如果输入为null则返回也是null等,具体可...

ADO.NET基础必备之SqlParameterCollection 类

SqlParameterCollection 类 表示与 SqlCommand 相关联的参数的集合以及各个参数到 DataSet 中列的映射。无法继承此类。 语法:  [ListBindableAttribute(false)] public sealed class SqlParameterCollection : DbParameterCollecti...

Essential.C#第五章 类

在第一章中你已经看到了如何声明一个新类Helloworld。在第二章,你也也学习了C#内建的原类型。你也知道了控制流,还有如何声明方法。现在是时候讨论如何定义属于自己的类型了。这在任何C#程序都是核心结构。C#作为一个面向对象的语言是完全支持类和构建对象。 本章为你引入c#的面向对象编程方式。重点是如何定义类,这是对象的模板。 在前面的章节的程序结构一直...