clsnetget.cls

来自「本书源码主要针对目前流行的FTP、HTTP、E-mail、Telnet、ICMP」· CLS 代码 · 共 326 行

CLS
326
字号
VERSION 1.0 CLASS
BEGIN
  MultiUse = -1  'True
  Persistable = 0  'NotPersistable
  DataBindingBehavior = 0  'vbNone
  DataSourceBehavior  = 0  'vbNone
  MTSTransactionMode  = 0  'NotAnMTSObject
END
Attribute VB_Name = "ClsNetGet"
Attribute VB_GlobalNameSpace = False
Attribute VB_Creatable = True
Attribute VB_PredeclaredId = False
Attribute VB_Exposed = False
Option Explicit

'打开并初始化Internet连接
Private Declare Function InternetOpen Lib "wininet.dll" Alias "InternetOpenA" _
        (ByVal lpszAgent As String, ByVal dwAccessType As Long, ByVal lpszProxyName As String, _
         ByVal lpszProxyBypass As String, ByVal dwFlags As Long) As Long

'关闭Internet连接或URL句柄
Private Declare Function InternetCloseHandle Lib "wininet.dll" (ByVal hInet As Long) As Integer

'打开一个URL,获得句柄
Private Declare Function InternetOpenUrl Lib "wininet.dll" Alias "InternetOpenUrlA" _
        (ByVal hInternetSession As Long, ByVal lpszUrl As String, ByVal lpszHeaders As String, _
         ByVal dwHeadersLength As Long, ByVal dwFlags As Long, ByVal dwContext As Long) As Long

'从打开的URL中读取数据(用于读取文本文件)
Private Declare Function InternetReadHtml Lib "wininet.dll" Alias "InternetReadFile" _
        (ByVal hFile As Long, ByVal lpBuffer As String, ByVal dwNumberOfBytesToRead As Long, _
         lNumberOfBytesRead As Long) As Integer
'从打开的URL中读取数据(用于读取二进制文件)
Private Declare Function InternetReadImg Lib "wininet.dll" Alias "InternetReadFile" _
        (ByVal hFile As Long, lpBuffer As Any, ByVal dwNumberOfBytesToRead As Long, _
         lNumberOfBytesRead As Long) As Integer

Private Const INTERNET_OPEN_TYPE_PRECONFIG = 0   '使用缺省的配置
Private Const INTERNET_FLAG_EXISITING_CONNECT = &H20000000
Private Const INTERNET_FLAG_RELOAD = &H80000000  '不从Cache中下载
Private Const scBlankStr = ""                    '空字符串常量

Private hInternetSession    As Long     ' Internet会话句柄
Private bInitialized        As Boolean  ' 标志是否已经初始化
Private hUrlFile            As Long     ' 打开的Url句柄
Private sContents           As String   ' html页面文本内容
Private sLastError          As String   ' 最近一次错误
Private sStatus             As String   ' 存放状态字符串的变量
Private objWindow           As Object   ' 显示状态字符串的窗口
Private sUserAgent          As String   ' 在HTTP协议中的UserAgent

'根据错误设置描述错误的变量
Sub CheckError()
Dim lLastErrorNo As Long
lLastErrorNo = Err.LastDllError
If lLastErrorNo > 0 Then sLastError = TranslateErrorCode(lLastErrorNo)
End Sub

'初始化过程,用于打开Internet会话及设置变量
Public Sub Init(Optional vInUserAgent As Variant)
On Error Resume Next
If IsMissing(vInUserAgent) Then
    sUserAgent = App.EXEName
Else
    sUserAgent = vInUserAgent
End If
Term
hUrlFile = 0
sContents = scBlankStr
sLastError = scBlankStr
sStatus = scBlankStr
'打开Internet连接
hInternetSession = InternetOpen(sUserAgent, INTERNET_OPEN_TYPE_PRECONFIG, vbNullString, vbNullString, 0)
bInitialized = CBool(hInternetSession)
End Sub

'分析Html文本,从中提取有用的文件链接
Public Function ParseHTML(ByVal sToken As String, colItems As Collection) As Boolean
Dim lPosInStr As Long
Dim lEndPosInStr1, lEndPosInStr2 As Long
Dim lStartPos As Long
Dim sAddItem As String
On Error Resume Next
'设置鼠标状态为等待
Screen.MousePointer = vbHourglass
SetStatus "分析Html页面开始..."
sContents = Replace(sContents, vbCrLf, "")
If Len(sContents) > Len(sToken) Then
    lStartPos = 1
    '查找字符串中的链接起始标志字符串sToken
    lPosInStr = InStr(lStartPos, sContents, sToken, vbTextCompare)
    '如果起始标志字符串找到
    While lPosInStr > 0
        DoEvents: DoEvents
        lPosInStr = lPosInStr + Len(sToken)
        '查找链接的结束位置
        If Mid(sContents, lPosInStr, 1) = """" Then
            lPosInStr = lPosInStr + 1
            lEndPosInStr1 = InStr(lPosInStr, sContents, """", vbTextCompare)
        ElseIf lEndPosInStr1 = 0 Then
            lEndPosInStr1 = InStr(lPosInStr, sContents, " ", vbTextCompare)
        Else
            lEndPosInStr1 = InStr(lPosInStr, sContents, ">", vbTextCompare)
        End If
        '得到链接字符串
        sAddItem = Mid(sContents, lPosInStr, lEndPosInStr1 - lPosInStr)
        '检查链接字符串
        lEndPosInStr1 = InStr(1, sAddItem, " ", vbTextCompare)
        lEndPosInStr2 = InStr(1, sAddItem, ">", vbTextCompare)
        If lEndPosInStr1 > 0 Or lEndPosInStr2 > 0 Then
            If lEndPosInStr1 > lEndPosInStr2 Then
                sAddItem = Mid(sAddItem, 1, lEndPosInStr1 - 1)
            Else
                sAddItem = Mid(sAddItem, 1, lEndPosInStr2 - 1)
            End If
        End If
        '将链接加入到集合中
        If Len(sAddItem) Then colItems.Add sAddItem, sAddItem
        lStartPos = lPosInStr + Len(sAddItem)
        lPosInStr = InStr(lStartPos, sContents, sToken, vbTextCompare)
    Wend
    ParseHTML = True
End If
SetStatus "分析Html页面结束"
'恢复鼠标状态为缺省
Screen.MousePointer = vbDefault
End Function


'从给定的Url取得html文件的内容。并保存在字符串sContents和指定的文件中
Public Function ReadUrlHtml(ByVal sUrl As String, Optional vFileName As Variant) As Boolean
Dim sReadBuffer As String * 2048        ' 为InternetReadFile函数提供字符串作为数据接收缓冲区
Dim lNumberOfBytesRead  As Long         ' 调用InternetReadFile函数读取的字节数
Dim lTotalBytesRead     As Long         ' 一共读取的字节数
Dim bDoLoop             As Boolean      ' 调用InternetReadFile的返回值
Dim i                   As Integer
On Error GoTo errReadUrl
'设置鼠标状态为等待
Screen.MousePointer = vbHourglass
SetStatus "下载开始: " & sUrl
'打开url下载
hUrlFile = InternetOpenUrl(hInternetSession, sUrl, vbNullString, 0, INTERNET_FLAG_EXISITING_CONNECT, 0)
If CBool(hUrlFile) Then
    sContents = scBlankStr
    bDoLoop = True
    While bDoLoop
        sReadBuffer = scBlankStr
        '从打开的InternetOpenUrl句柄中读取文件数据
        bDoLoop = InternetReadHtml(hUrlFile, sReadBuffer, Len(sReadBuffer), lNumberOfBytesRead)
        If Not CBool(bDoLoop) Then CheckError
        lTotalBytesRead = lTotalBytesRead + lNumberOfBytesRead
        SetStatus "读取" & CStr(lTotalBytesRead) & "字节:" & sUrl
        If CBool(lNumberOfBytesRead) Then
            '将读取的数据保存到变量sContents中,分析链接时要使用
            sContents = sContents & Left$(sReadBuffer, lNumberOfBytesRead)
        Else
            bDoLoop = False
        End If
    Wend
    '关闭InternetOpenUrl打开的句柄
    InternetCloseHandle (hUrlFile)
    '将读取的数据存到指定的文件中
    If Len(sContents) > 0 Then
        Dim iFileNum As Integer
        iFileNum = FreeFile
        Open CStr(vFileName) For Binary As iFileNum
        Put #iFileNum, , sContents
        Close (iFileNum)
        ReadUrlHtml = True
    Else
        ReadUrlHtml = False
    End If
Else
    CheckError
End If
SetStatus "下载完毕:" & sUrl
'设置鼠标为缺省状态
Screen.MousePointer = vbDefault
Exit Function
errReadUrl:
sLastError = Error$(Err)
Screen.MousePointer = vbDefault
Exit Function
End Function


'从给定的Url取得二进制文件的内容。并保存到指定的文件
Public Function ReadUrlImg(ByVal sUrl As String, Optional vFileName As Variant) As Boolean
Dim sReadBuffer(2048)   As Byte         '为InternetReadFile函数提供字符串作为数据接收缓冲区
Dim lNumberOfBytesRead  As Long         '调用InternetReadFile函数读取的字节数
Dim lTotalBytesRead     As Long         '一共读取的字节数
Dim bDoLoop             As Boolean      '调用InternetReadFile的返回值
Dim i                   As Integer
On Error GoTo errReadUrl
Screen.MousePointer = vbHourglass
SetStatus "下载开始: " & sUrl
If IsMissing(vFileName) Then
    ReadUrlImg = False
    Exit Function
End If
'打开url下载
hUrlFile = InternetOpenUrl(hInternetSession, sUrl, vbNullString, 0, INTERNET_FLAG_EXISITING_CONNECT, 0)
If CBool(hUrlFile) Then
    sContents = scBlankStr
    bDoLoop = True
    Dim iFileNum As Integer
    While bDoLoop
        '从打开的InternetOpenUrl句柄中读取文件数据
        bDoLoop = InternetReadImg(hUrlFile, sReadBuffer(0), 2048, lNumberOfBytesRead)
        If Not CBool(bDoLoop) Then CheckError
        lTotalBytesRead = lTotalBytesRead + lNumberOfBytesRead
        SetStatus "读取" & CStr(lTotalBytesRead) & "字节:" & sUrl
        If CBool(lNumberOfBytesRead) Then
            '读取的数据存到指定的文件中
            If iFileNum = 0 Then
                iFileNum = FreeFile
                Open CStr(vFileName) For Binary As iFileNum
            End If
            For i = 0 To lNumberOfBytesRead - 1
                Put #iFileNum, , sReadBuffer(i)
            Next i
        Else
            bDoLoop = False
        End If
    Wend
    '关闭InternetOpenUrl打开的句柄
    InternetCloseHandle (hUrlFile)
    If iFileNum <> 0 Then
        Close (iFileNum)
        ReadUrlImg = True
    Else
        ReadUrlImg = False
    End If
Else
    CheckError
End If
SetStatus "下载完毕:" & sUrl
'设置鼠标为缺省状态
Screen.MousePointer = vbDefault
Exit Function
errReadUrl:
sLastError = Error$(Err)
Screen.MousePointer = vbDefault
Exit Function
End Function

'根据下载的状态设置窗口的文字
Private Sub SetStatus(sInStatus As String)
On Error Resume Next
objWindow = sInStatus
DoEvents
End Sub

'结束程序所做的一些处理,释放资源
Public Sub Term()
On Error Resume Next
If InternetCloseHandle(hInternetSession) Then
    bInitialized = False
    SetStatus ("Ready")
Else
    CheckError
End If
End Sub

'解释错误码
Function TranslateErrorCode(ByVal lErrorCode As Long) As String
Select Case lErrorCode
    Case 12001: TranslateErrorCode = "No more handles could be generated at this time"
    Case 12002: TranslateErrorCode = "The request has timed out."
    Case 12003: TranslateErrorCode = "An extended error was returned from the server."
    Case 12004: TranslateErrorCode = "An internal error has occurred."
    Case 12005: TranslateErrorCode = "The URL is invalid."
    Case 12006: TranslateErrorCode = "The URL scheme could not be recognized, or is not supported."
    Case 12007: TranslateErrorCode = "The server name could not be resolved."
    Case 12008: TranslateErrorCode = "The requested protocol could not be located."
    Case 12009: TranslateErrorCode = "A request to InternetQueryOption or InternetSetOption specified an invalid option value."
    Case 12010: TranslateErrorCode = "The length of an option supplied to InternetQueryOption or InternetSetOption is incorrect for the type of option specified."
    Case 12011: TranslateErrorCode = "The request option can not be set, only queried. "
    Case 12012: TranslateErrorCode = "The Win32 Internet support is being shutdown or unloaded."
    Case 12013: TranslateErrorCode = "The request to connect and login to an FTP server could not be completed because the supplied user name is incorrect."
    Case 12014: TranslateErrorCode = "The request to connect and login to an FTP server could not be completed because the supplied password is incorrect. "
    Case 12015: TranslateErrorCode = "The request to connect to and login to an FTP server failed."
    Case 12016: TranslateErrorCode = "The requested operation is invalid. "
    Case 12017: TranslateErrorCode = "The operation was canceled, usually because the handle on which the request was operating was closed before the operation completed."
    Case 12018: TranslateErrorCode = "The type of handle supplied is incorrect for this operation."
    Case 12019: TranslateErrorCode = "The requested operation can not be carried out because the handle supplied is not in the correct state."
    Case 12020: TranslateErrorCode = "The request can not be made via a proxy."
    Case 12021: TranslateErrorCode = "A required registry value could not be located. "
    Case 12022: TranslateErrorCode = "A required registry value was located but is an incorrect type or has an invalid value."
    Case 12023: TranslateErrorCode = "Direct network access cannot be made at this time. "
    Case 12024: TranslateErrorCode = "An asynchronous request could not be made because a zero context value was supplied."
    Case 12025: TranslateErrorCode = "An asynchronous request could not be made because a callback function has not been set."
    Case 12026: TranslateErrorCode = "The required operation could not be completed because one or more requests are pending."
    Case 12027: TranslateErrorCode = "The format of the request is invalid."
    Case 12028: TranslateErrorCode = "The requested item could not be located."
    Case 12029: TranslateErrorCode = "The attempt to connect to the server failed."
    Case 12030: TranslateErrorCode = "The connection with the server has been terminated."
    Case 12031: TranslateErrorCode = "The connection with the server has been reset."
    Case 12036: TranslateErrorCode = "The request failed because the handle already exists."
    Case Else: TranslateErrorCode = "Error details not available."
End Select
End Function

'设置用于显示描述信息的窗口
Property Let SetStatusWindow(objStatusWindow As Object)
On Error Resume Next
Set objWindow = objStatusWindow
End Property

'获得最近的一次错误信息
Property Get GetLastError() As String
GetLastError = sLastError
End Property

'设置程序名(在InternetOpen函数中使用)
Property Let SetUserAgent(sInUserAgent As String)
If Len(sInUserAgent) > 0 Then sUserAgent = sInUserAgent
End Property

'类对象使用结束
Private Sub Class_Terminate()
Term
End Sub


⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?