Excel VBA: Download files from the Internet

Microsoft ExcelLeave a Comment on Excel VBA: Download files from the Internet

Excel VBA: Download files from the Internet

There is no built-in function in Microsoft Excel which allows you to download contents from the Internet on the fly. To accomplish this task we need to use the API for WinInet. The use and explanation of API in VBA is for advanced users which have prior experience from either Visual Basic 6.0 or .NET.

Pitfalls

It is very important that all open Internet connections are closed as soon as the task is completed. WinInet only allows 2 concurrent connections to a given host. If you forget to shut down the connection after use, you will experience timeouts and misleading error messages. Please refer to the following website for more information related to the maximum allowed concurrent web connections:

Howto

The source code below should be pasted in a “Class Module” in Excel. If you are not sure how to open the VBA editor in Excel for your current Microsoft Office version, please refer to the following page:

Create new class module:

  1. Open the Microsoft Visual Basic for Applications editor in Excel.
  2. Select Insert > Class Module on the main menubar
  3. Rename the new class module to “WebClient

Example

To use the code, you shold create a new instance of the class and any of the public methods:

  • DownloadFile – download a specific resource to a local file
  • UrlExists – check if a given URL exists
Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
Dim objClient As New WebClient
Call objClient.DownloadFile("http://www.google.com", "c:\test.html")
Dim objClient As New WebClient Call objClient.DownloadFile("http://www.google.com", "c:\test.html")
Dim objClient As New WebClient
Call objClient.DownloadFile("http://www.google.com", "c:\test.html")

Dependencies

The function “ReThrowError” is defined here:

Source Code

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
' API
Private Declare Function InternetOpen Lib "wininet.dll" Alias "InternetOpenA" (ByVal sAgent As String, ByVal lAccessType As Long, ByVal sProxyName As String, ByVal sProxyBypass As String, ByVal lFlags As Long) As Long
Private Declare Function InternetCloseHandle Lib "wininet.dll" (ByVal hInet As Long) As Integer
Private Declare Function InternetReadFile Lib "wininet.dll" (ByVal hFile As Long, ByVal sBuffer As String, ByVal lNumBytesToRead As Long, lNumberOfBytesRead As Long) As Integer
Private Declare Function InternetConnect Lib "wininet.dll" Alias "InternetConnectA" (ByVal hInternetSession As Long, ByVal sServerName As String, ByVal nServerPort As Integer, ByVal sUsername As String, ByVal sPassword As String, ByVal lService As Long, ByVal lFlags As Long, ByVal lContext As Long) As Long
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
Private Declare Function InternetGetLastResponseInfo Lib "wininet.dll" Alias "InternetGetLastResponseInfoA" (lpdwError As Long, ByVal lpszBuffer As String, lpdwBufferLength As Long) As Boolean
Private Enum EHttpQueryInfoLevel
http_QUERY_CONTENT_TYPE = 1
http_QUERY_CONTENT_LENGTH = 5
http_QUERY_EXPIRES = 10
http_QUERY_LAST_MODIFIED = 11
http_QUERY_PRAGMA = 17
http_QUERY_VERSION = 18
http_QUERY_STATUS_CODE = 19
http_QUERY_STATUS_TEXT = 20
http_QUERY_RAW_HEADERS = 21
http_QUERY_RAW_HEADERS_CRLF = 22
http_QUERY_FORWARDED = 30
http_QUERY_SERVER = 37
http_QUERY_USER_AGENT = 39
http_QUERY_SET_COOKIE = 43
http_QUERY_REQUEST_METHOD = 45
http_STATUS_DENIED = 401
http_STATUS_PROXY_AUTH_REQ = 407
End Enum
Private Declare Function HttpQueryInfo Lib "wininet.dll" Alias "HttpQueryInfoA" (ByVal hhttpRequest As Long, ByVal lInfoLevel As Long, ByRef sBuffer As Any, ByRef lBufferLength As Long, ByRef lIndex As Long) As Integer
Private Declare Function HttpOpenRequest Lib "wininet.dll" Alias "HttpOpenRequestA" (ByVal hHttpSession As Long, ByVal sVerb As String, ByVal sObjectName As String, ByVal sVersion As String, ByVal sReferer As String, ByVal something As Long, ByVal lFlags As Long, ByVal lContext As Long) As Long
Private Declare Function HttpSendRequest Lib "wininet.dll" Alias "HttpSendRequestA" (ByVal hhttpRequest As Long, ByVal sHeaders As String, ByVal lHeadersLength As Long, sOptional As Any, ByVal lOptionalLength As Long) As Integer
' Constants
Private Const INTERNET_FLAG_NO_CACHE_WRITE As Long = &H4000000
Private Const INTERNET_FLAG_NO_UI As Long = &H200
Private Const INTERNET_FLAG_EXISTING_CONNECT As Long = &H20000000
Private Const INTERNET_FLAG_RELOAD As Long = &H80000000
Private Const INTERNET_OPEN_TYPE_PRECONFIG = 0
Private Const INTERNET_OPEN_TYPE_DIRECT = 1
Private Const INTERNET_OPEN_TYPE_PROXY = 3
' User Agent
Private Const USER_AGENT = "Mozilla/5.0 (compatible; MSIE 10.0; Windows NT 6.1; WOW64; Trident/6.0)"
' Open
Private Function OpenSession()
Dim hSession As Long
' Open internet connection
hSession = InternetOpen(USER_AGENT, INTERNET_OPEN_TYPE_PRECONFIG, vbNullString, vbNullString, 0)
' Valid session?
If (hSession = 0) Then
' Error
Err.Raise 1234, , "Unable to open internet connection!"
' Finished
Exit Function
End If
' Get the value
OpenSession = hSession
End Function
' Close Handle
Private Sub CloseHandle(ByRef hHandle As Long)
' Valid handle?
If (hHandle <> 0) Then
' Close
Call InternetCloseHandle(hHandle)
' Clear handle
hHandle = 0
End If
End Sub
' Open Url
Private Function OpenUrl(ByVal hSession As Long, ByVal strUrl As String, Optional ByVal bRaiseError = True) As Long
Dim hConnection As Long
' Valid session?
If (hSession = 0) Then
Err.Raise 2345345, , "The session is not set!"
Exit Function
End If
' Open Url
hConnection = InternetOpenUrl(hSession, strUrl, vbNullString, ByVal 0&, INTERNET_FLAG_EXISTING_CONNECT Or INTERNET_FLAG_RELOAD, ByVal 0&)
' Valid file?
If (hConnection = 0) Then
' Error
Call RaiseLastError
' Exit
Exit Function
End If
' Get the value
OpenUrl = hConnection
End Function
' Raise Last Error
Private Sub RaiseLastError()
Dim strErrorMessage As String
Dim lngErrorNumber As Long
' Get the last error
lngErrorNumber = Err.LastDllError
' Valid error?
If (lngErrorNumber <> 0) Then
' Error
Err.Raise lngErrorNumber, , "DLL Error: " & CStr(lngErrorNumber)
Else
' Get the error
If (GetLastResponseInfo(lngErrorNumber, strErrorMessage)) Then
' Raise error
Err.Raise lngErrorNumber, , strErrorMessage
End If
End If
End Sub
' Get Last Response Info
Private Function GetLastResponseInfo(ByRef lngErrorNumber As Long, ByRef strErrorMessage As String) As Boolean
Dim intResult As Integer
Dim lngBufferLength As Long
' Get the required buffer size
intResult = InternetGetLastResponseInfo(lngErrorNumber, strErrorMessage, lngBufferLength)
' Valid length?
If (lngErrorNumber <> 0) Then
' Allcoate the buffer
strErrorMessage = String(lngBufferLength, 0)
' Retrieve the last respons info
intResult = InternetGetLastResponseInfo(lngErrorNumber, strErrorMessage, lngBufferLength)
' Get the error message
GetLastResponseInfo = True
Exit Function
End If
' Not an error
GetLastResponseInfo = False
End Function
' File Exists?
Public Function UrlExists(ByVal strUrl As String) As Boolean
On Error GoTo ErrorHandler
Const BUFFER_LENGTH As Long = 255
Dim hSession As Long
Dim hConnection As Long
Dim strBuffer As String * BUFFER_LENGTH
Dim intBufferLength As Long
Dim intResult As Integer
Dim lngIndex As Long
Dim strStatusCode As String
Dim intStatusCode As Integer
' Open Session
hSession = OpenSession
' Open the file
hConnection = OpenUrl(hSession, strUrl, False)
' Set the default bufferlength
intBufferLength = BUFFER_LENGTH
' Get the status code
intResult = HttpQueryInfo(hConnection, http_QUERY_STATUS_CODE, ByVal strBuffer, intBufferLength, lngIndex)
' Valid value?
If (intResult <> 0) Then
' Get the status code string
strStatusCode = Left(strBuffer, intBufferLength)
' Get the integer status code
intStatusCode = CInt(strStatusCode)
' Check the status code
UrlExists = (intStatusCode = 200)
End If
' Close the connection
Call CloseHandle(hConnection)
Call CloseHandle(hSession)
Exit Function
ErrorHandler:
Call CloseHandle(hConnection)
Call CloseHandle(hSession)
' Re-throw
Call ReThrowError(Err)
End Function
' Download File
Public Sub DownloadFile(ByVal strUrl As String, ByVal strFilename As String)
On Error GoTo ErrorHandling
' Buffer size
Const BUFFER_SIZE As Integer = 4096
Dim hSession As Long
Dim hConnection As Long
Dim strBuffer As String * BUFFER_SIZE
Dim intFile As Integer
Dim lngRead As Long
Dim intResult As Integer
' Open session
hSession = OpenSession()
' Open the file
hConnection = OpenUrl(hSession, strUrl)
' Find free file
intFile = FreeFile
' Create file
Open strFilename For Binary As #intFile
Do
' Read the data
intResult = InternetReadFile(hConnection, strBuffer, BUFFER_SIZE, lngRead)
' Valid function?
If (intResult <> 0) Then
' Valid number of bytes read?
If (lngRead > 0) Then
' Is less than buffer size?
If (lngRead < BUFFER_SIZE) Then
' Get only the relevant data
strBuffer = Left(strBuffer, lngRead)
End If
' Write the data
Put #intFile, , strBuffer
End If
End If
Loop While (lngRead > 0)
' Close the file
Close #intFile
ExitMe:
' Close connection
Call CloseHandle(hConnection)
Call CloseHandle(hSession)
Exit Sub
ErrorHandling:
' Close connection
Call CloseHandle(hConnection)
Call CloseHandle(hSession)
' Rethrow
Call ReThrowError(Err)
End Sub
' API Private Declare Function InternetOpen Lib "wininet.dll" Alias "InternetOpenA" (ByVal sAgent As String, ByVal lAccessType As Long, ByVal sProxyName As String, ByVal sProxyBypass As String, ByVal lFlags As Long) As Long Private Declare Function InternetCloseHandle Lib "wininet.dll" (ByVal hInet As Long) As Integer Private Declare Function InternetReadFile Lib "wininet.dll" (ByVal hFile As Long, ByVal sBuffer As String, ByVal lNumBytesToRead As Long, lNumberOfBytesRead As Long) As Integer Private Declare Function InternetConnect Lib "wininet.dll" Alias "InternetConnectA" (ByVal hInternetSession As Long, ByVal sServerName As String, ByVal nServerPort As Integer, ByVal sUsername As String, ByVal sPassword As String, ByVal lService As Long, ByVal lFlags As Long, ByVal lContext As Long) As Long 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 Private Declare Function InternetGetLastResponseInfo Lib "wininet.dll" Alias "InternetGetLastResponseInfoA" (lpdwError As Long, ByVal lpszBuffer As String, lpdwBufferLength As Long) As Boolean Private Enum EHttpQueryInfoLevel http_QUERY_CONTENT_TYPE = 1 http_QUERY_CONTENT_LENGTH = 5 http_QUERY_EXPIRES = 10 http_QUERY_LAST_MODIFIED = 11 http_QUERY_PRAGMA = 17 http_QUERY_VERSION = 18 http_QUERY_STATUS_CODE = 19 http_QUERY_STATUS_TEXT = 20 http_QUERY_RAW_HEADERS = 21 http_QUERY_RAW_HEADERS_CRLF = 22 http_QUERY_FORWARDED = 30 http_QUERY_SERVER = 37 http_QUERY_USER_AGENT = 39 http_QUERY_SET_COOKIE = 43 http_QUERY_REQUEST_METHOD = 45 http_STATUS_DENIED = 401 http_STATUS_PROXY_AUTH_REQ = 407 End Enum Private Declare Function HttpQueryInfo Lib "wininet.dll" Alias "HttpQueryInfoA" (ByVal hhttpRequest As Long, ByVal lInfoLevel As Long, ByRef sBuffer As Any, ByRef lBufferLength As Long, ByRef lIndex As Long) As Integer Private Declare Function HttpOpenRequest Lib "wininet.dll" Alias "HttpOpenRequestA" (ByVal hHttpSession As Long, ByVal sVerb As String, ByVal sObjectName As String, ByVal sVersion As String, ByVal sReferer As String, ByVal something As Long, ByVal lFlags As Long, ByVal lContext As Long) As Long Private Declare Function HttpSendRequest Lib "wininet.dll" Alias "HttpSendRequestA" (ByVal hhttpRequest As Long, ByVal sHeaders As String, ByVal lHeadersLength As Long, sOptional As Any, ByVal lOptionalLength As Long) As Integer ' Constants Private Const INTERNET_FLAG_NO_CACHE_WRITE As Long = &H4000000 Private Const INTERNET_FLAG_NO_UI As Long = &H200 Private Const INTERNET_FLAG_EXISTING_CONNECT As Long = &H20000000 Private Const INTERNET_FLAG_RELOAD As Long = &H80000000 Private Const INTERNET_OPEN_TYPE_PRECONFIG = 0 Private Const INTERNET_OPEN_TYPE_DIRECT = 1 Private Const INTERNET_OPEN_TYPE_PROXY = 3 ' User Agent Private Const USER_AGENT = "Mozilla/5.0 (compatible; MSIE 10.0; Windows NT 6.1; WOW64; Trident/6.0)" ' Open Private Function OpenSession() Dim hSession As Long ' Open internet connection hSession = InternetOpen(USER_AGENT, INTERNET_OPEN_TYPE_PRECONFIG, vbNullString, vbNullString, 0) ' Valid session? If (hSession = 0) Then ' Error Err.Raise 1234, , "Unable to open internet connection!" ' Finished Exit Function End If ' Get the value OpenSession = hSession End Function ' Close Handle Private Sub CloseHandle(ByRef hHandle As Long) ' Valid handle? If (hHandle <> 0) Then ' Close Call InternetCloseHandle(hHandle) ' Clear handle hHandle = 0 End If End Sub ' Open Url Private Function OpenUrl(ByVal hSession As Long, ByVal strUrl As String, Optional ByVal bRaiseError = True) As Long Dim hConnection As Long ' Valid session? If (hSession = 0) Then Err.Raise 2345345, , "The session is not set!" Exit Function End If ' Open Url hConnection = InternetOpenUrl(hSession, strUrl, vbNullString, ByVal 0&, INTERNET_FLAG_EXISTING_CONNECT Or INTERNET_FLAG_RELOAD, ByVal 0&) ' Valid file? If (hConnection = 0) Then ' Error Call RaiseLastError ' Exit Exit Function End If ' Get the value OpenUrl = hConnection End Function ' Raise Last Error Private Sub RaiseLastError() Dim strErrorMessage As String Dim lngErrorNumber As Long ' Get the last error lngErrorNumber = Err.LastDllError ' Valid error? If (lngErrorNumber <> 0) Then ' Error Err.Raise lngErrorNumber, , "DLL Error: " & CStr(lngErrorNumber) Else ' Get the error If (GetLastResponseInfo(lngErrorNumber, strErrorMessage)) Then ' Raise error Err.Raise lngErrorNumber, , strErrorMessage End If End If End Sub ' Get Last Response Info Private Function GetLastResponseInfo(ByRef lngErrorNumber As Long, ByRef strErrorMessage As String) As Boolean Dim intResult As Integer Dim lngBufferLength As Long ' Get the required buffer size intResult = InternetGetLastResponseInfo(lngErrorNumber, strErrorMessage, lngBufferLength) ' Valid length? If (lngErrorNumber <> 0) Then ' Allcoate the buffer strErrorMessage = String(lngBufferLength, 0) ' Retrieve the last respons info intResult = InternetGetLastResponseInfo(lngErrorNumber, strErrorMessage, lngBufferLength) ' Get the error message GetLastResponseInfo = True Exit Function End If ' Not an error GetLastResponseInfo = False End Function ' File Exists? Public Function UrlExists(ByVal strUrl As String) As Boolean On Error GoTo ErrorHandler Const BUFFER_LENGTH As Long = 255 Dim hSession As Long Dim hConnection As Long Dim strBuffer As String * BUFFER_LENGTH Dim intBufferLength As Long Dim intResult As Integer Dim lngIndex As Long Dim strStatusCode As String Dim intStatusCode As Integer ' Open Session hSession = OpenSession ' Open the file hConnection = OpenUrl(hSession, strUrl, False) ' Set the default bufferlength intBufferLength = BUFFER_LENGTH ' Get the status code intResult = HttpQueryInfo(hConnection, http_QUERY_STATUS_CODE, ByVal strBuffer, intBufferLength, lngIndex) ' Valid value? If (intResult <> 0) Then ' Get the status code string strStatusCode = Left(strBuffer, intBufferLength) ' Get the integer status code intStatusCode = CInt(strStatusCode) ' Check the status code UrlExists = (intStatusCode = 200) End If ' Close the connection Call CloseHandle(hConnection) Call CloseHandle(hSession) Exit Function ErrorHandler: Call CloseHandle(hConnection) Call CloseHandle(hSession) ' Re-throw Call ReThrowError(Err) End Function ' Download File Public Sub DownloadFile(ByVal strUrl As String, ByVal strFilename As String) On Error GoTo ErrorHandling ' Buffer size Const BUFFER_SIZE As Integer = 4096 Dim hSession As Long Dim hConnection As Long Dim strBuffer As String * BUFFER_SIZE Dim intFile As Integer Dim lngRead As Long Dim intResult As Integer ' Open session hSession = OpenSession() ' Open the file hConnection = OpenUrl(hSession, strUrl) ' Find free file intFile = FreeFile ' Create file Open strFilename For Binary As #intFile Do ' Read the data intResult = InternetReadFile(hConnection, strBuffer, BUFFER_SIZE, lngRead) ' Valid function? If (intResult <> 0) Then ' Valid number of bytes read? If (lngRead > 0) Then ' Is less than buffer size? If (lngRead < BUFFER_SIZE) Then ' Get only the relevant data strBuffer = Left(strBuffer, lngRead) End If ' Write the data Put #intFile, , strBuffer End If End If Loop While (lngRead > 0) ' Close the file Close #intFile ExitMe: ' Close connection Call CloseHandle(hConnection) Call CloseHandle(hSession) Exit Sub ErrorHandling: ' Close connection Call CloseHandle(hConnection) Call CloseHandle(hSession) ' Rethrow Call ReThrowError(Err) End Sub
' API
Private Declare Function InternetOpen Lib "wininet.dll" Alias "InternetOpenA" (ByVal sAgent As String, ByVal lAccessType As Long, ByVal sProxyName As String, ByVal sProxyBypass As String, ByVal lFlags As Long) As Long
Private Declare Function InternetCloseHandle Lib "wininet.dll" (ByVal hInet As Long) As Integer
Private Declare Function InternetReadFile Lib "wininet.dll" (ByVal hFile As Long, ByVal sBuffer As String, ByVal lNumBytesToRead As Long, lNumberOfBytesRead As Long) As Integer
Private Declare Function InternetConnect Lib "wininet.dll" Alias "InternetConnectA" (ByVal hInternetSession As Long, ByVal sServerName As String, ByVal nServerPort As Integer, ByVal sUsername As String, ByVal sPassword As String, ByVal lService As Long, ByVal lFlags As Long, ByVal lContext As Long) As Long
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
Private Declare Function InternetGetLastResponseInfo Lib "wininet.dll" Alias "InternetGetLastResponseInfoA" (lpdwError As Long, ByVal lpszBuffer As String, lpdwBufferLength As Long) As Boolean

Private Enum EHttpQueryInfoLevel
    http_QUERY_CONTENT_TYPE = 1
    http_QUERY_CONTENT_LENGTH = 5
    http_QUERY_EXPIRES = 10
    http_QUERY_LAST_MODIFIED = 11
    http_QUERY_PRAGMA = 17
    http_QUERY_VERSION = 18
    http_QUERY_STATUS_CODE = 19
    http_QUERY_STATUS_TEXT = 20
    http_QUERY_RAW_HEADERS = 21
    http_QUERY_RAW_HEADERS_CRLF = 22
    http_QUERY_FORWARDED = 30
    http_QUERY_SERVER = 37
    http_QUERY_USER_AGENT = 39
    http_QUERY_SET_COOKIE = 43
    http_QUERY_REQUEST_METHOD = 45
    http_STATUS_DENIED = 401
    http_STATUS_PROXY_AUTH_REQ = 407
End Enum

Private Declare Function HttpQueryInfo Lib "wininet.dll" Alias "HttpQueryInfoA" (ByVal hhttpRequest As Long, ByVal lInfoLevel As Long, ByRef sBuffer As Any, ByRef lBufferLength As Long, ByRef lIndex As Long) As Integer
Private Declare Function HttpOpenRequest Lib "wininet.dll" Alias "HttpOpenRequestA" (ByVal hHttpSession As Long, ByVal sVerb As String, ByVal sObjectName As String, ByVal sVersion As String, ByVal sReferer As String, ByVal something As Long, ByVal lFlags As Long, ByVal lContext As Long) As Long
Private Declare Function HttpSendRequest Lib "wininet.dll" Alias "HttpSendRequestA" (ByVal hhttpRequest As Long, ByVal sHeaders As String, ByVal lHeadersLength As Long, sOptional As Any, ByVal lOptionalLength As Long) As Integer

' Constants
Private Const INTERNET_FLAG_NO_CACHE_WRITE As Long = &H4000000
Private Const INTERNET_FLAG_NO_UI As Long = &H200
Private Const INTERNET_FLAG_EXISTING_CONNECT As Long = &H20000000
Private Const INTERNET_FLAG_RELOAD As Long = &H80000000

Private Const INTERNET_OPEN_TYPE_PRECONFIG = 0
Private Const INTERNET_OPEN_TYPE_DIRECT = 1
Private Const INTERNET_OPEN_TYPE_PROXY = 3


' User Agent
Private Const USER_AGENT = "Mozilla/5.0 (compatible; MSIE 10.0; Windows NT 6.1; WOW64; Trident/6.0)"



' Open
Private Function OpenSession()
    Dim hSession As Long

    ' Open internet connection
    hSession = InternetOpen(USER_AGENT, INTERNET_OPEN_TYPE_PRECONFIG, vbNullString, vbNullString, 0)

    ' Valid session?
    If (hSession = 0) Then
        ' Error
        Err.Raise 1234, , "Unable to open internet connection!"
        
        ' Finished
        Exit Function
    End If
    
    ' Get the value
    OpenSession = hSession
End Function

' Close Handle
Private Sub CloseHandle(ByRef hHandle As Long)
   ' Valid handle?
   If (hHandle <> 0) Then
        ' Close
        Call InternetCloseHandle(hHandle)
        
        ' Clear handle
        hHandle = 0
    End If
End Sub


' Open Url
Private Function OpenUrl(ByVal hSession As Long, ByVal strUrl As String, Optional ByVal bRaiseError = True) As Long
    Dim hConnection As Long
    
    ' Valid session?
    If (hSession = 0) Then
        Err.Raise 2345345, , "The session is not set!"
        Exit Function
    End If
    
    ' Open Url
    hConnection = InternetOpenUrl(hSession, strUrl, vbNullString, ByVal 0&, INTERNET_FLAG_EXISTING_CONNECT Or INTERNET_FLAG_RELOAD, ByVal 0&)

     ' Valid file?
    If (hConnection = 0) Then
        ' Error
        Call RaiseLastError
        
        ' Exit
        Exit Function
    End If

    ' Get the value
    OpenUrl = hConnection

End Function

' Raise Last Error
Private Sub RaiseLastError()
    Dim strErrorMessage As String
    Dim lngErrorNumber As Long

    ' Get the last error
    lngErrorNumber = Err.LastDllError
    
    ' Valid error?
    If (lngErrorNumber <> 0) Then
        ' Error
        Err.Raise lngErrorNumber, , "DLL Error: " & CStr(lngErrorNumber)
    Else
        ' Get the error
        If (GetLastResponseInfo(lngErrorNumber, strErrorMessage)) Then
            ' Raise error
            Err.Raise lngErrorNumber, , strErrorMessage
        End If
    End If
End Sub

' Get Last Response Info
Private Function GetLastResponseInfo(ByRef lngErrorNumber As Long, ByRef strErrorMessage As String) As Boolean
    Dim intResult As Integer
    Dim lngBufferLength As Long
    
    ' Get the required buffer size
    intResult = InternetGetLastResponseInfo(lngErrorNumber, strErrorMessage, lngBufferLength)
        
    ' Valid length?
    If (lngErrorNumber <> 0) Then
        ' Allcoate the buffer
        strErrorMessage = String(lngBufferLength, 0)
        
        ' Retrieve the last respons info
        intResult = InternetGetLastResponseInfo(lngErrorNumber, strErrorMessage, lngBufferLength)
    
        ' Get the error message
        GetLastResponseInfo = True
        Exit Function
    End If
    
    ' Not an error
    GetLastResponseInfo = False
End Function


' File Exists?
Public Function UrlExists(ByVal strUrl As String) As Boolean
    On Error GoTo ErrorHandler
    
    Const BUFFER_LENGTH As Long = 255
    
    Dim hSession As Long
    Dim hConnection As Long
    Dim strBuffer As String * BUFFER_LENGTH
    Dim intBufferLength As Long
    Dim intResult As Integer
    Dim lngIndex As Long
    Dim strStatusCode As String
    Dim intStatusCode As Integer
    
    ' Open Session
    hSession = OpenSession
    
    ' Open the file
    hConnection = OpenUrl(hSession, strUrl, False)
    
    ' Set the default bufferlength
    intBufferLength = BUFFER_LENGTH
    
    ' Get the status code
    intResult = HttpQueryInfo(hConnection, http_QUERY_STATUS_CODE, ByVal strBuffer, intBufferLength, lngIndex)
    
    ' Valid value?
    If (intResult <> 0) Then
        ' Get the status code string
        strStatusCode = Left(strBuffer, intBufferLength)
        
        ' Get the integer status code
        intStatusCode = CInt(strStatusCode)
        
        ' Check the status code
        UrlExists = (intStatusCode = 200)
    End If
    
    ' Close the connection
    Call CloseHandle(hConnection)
    Call CloseHandle(hSession)
    Exit Function
    
ErrorHandler:
    Call CloseHandle(hConnection)
    Call CloseHandle(hSession)
    
    ' Re-throw
    Call ReThrowError(Err)
End Function


' Download File
Public Sub DownloadFile(ByVal strUrl As String, ByVal strFilename As String)
    On Error GoTo ErrorHandling
    
    ' Buffer size
    Const BUFFER_SIZE As Integer = 4096
    
    Dim hSession As Long
    Dim hConnection As Long
    Dim strBuffer As String * BUFFER_SIZE
    Dim intFile As Integer
    Dim lngRead As Long
    Dim intResult As Integer

    ' Open session
    hSession = OpenSession()

    ' Open the file
    hConnection = OpenUrl(hSession, strUrl)
    
    ' Find free file
    intFile = FreeFile
    
    ' Create file
    Open strFilename For Binary As #intFile
    
        Do
            ' Read the data
            intResult = InternetReadFile(hConnection, strBuffer, BUFFER_SIZE, lngRead)
    
            ' Valid function?
            If (intResult <> 0) Then
            
                ' Valid number of bytes read?
                If (lngRead > 0) Then
                
                    ' Is less than buffer size?
                    If (lngRead < BUFFER_SIZE) Then
                    
                        ' Get only the relevant data
                        strBuffer = Left(strBuffer, lngRead)
                    End If
                
                    ' Write the data
                    Put #intFile, , strBuffer
                End If
            End If
            
        Loop While (lngRead > 0)
        
    ' Close the file
    Close #intFile
    
ExitMe:
    ' Close connection
    Call CloseHandle(hConnection)
    Call CloseHandle(hSession)
    Exit Sub
    
ErrorHandling:
    ' Close connection
    Call CloseHandle(hConnection)
    Call CloseHandle(hSession)
     
    ' Rethrow
    Call ReThrowError(Err)

End Sub

Related

Ulf Emsoy has long working experience in project management, software development and supply chain management.

Leave a Reply

Your email address will not be published. Required fields are marked *

Back To Top