Option Explicit On Option Strict Off Option Compare Binary '============================================================================================================= ' ' cDownload.vb ' ------------ ' ' Created By : Kevin Wilson ' ' Last Update : January 05, 2004 ' Created On : November 24, 2003 ' ' VB Versions : VB.NET 1.1 (VS.NET 2003) ' ' Requires : The .NET Framework v1.1 ' ' Description : This class module makes it easy to download files and track the download progress in real time. ' ' Example Use : ' '------------------------------------------------------------------------------------------------------------- ' ' Private WithEvents m_objDownload As cDownload ' Public Sub frmMain_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load ' Dim iErrNum As Integer ' Dim sErrSrc As String ' Dim sErrDesc As String ' Me.Visible = True ' Me.Refresh() ' m_objDownload = New cDownload("http://www.thevbzone.com/files/", "C:\") ' If m_objDownload.DownloadFile("AppTools.msi", , , iErrNum, sErrSrc, sErrDesc) = False Then ' MsgBox("Error Downloading File:" & Chr(13) & Chr(13) & _ ' "Error Number = " & iErrNum & Chr(13) & _ ' "Error Source = " & sErrSrc & Chr(13) & _ ' "Error Description = " & sErrDesc, MsgBoxStyle.OKOnly Or MsgBoxStyle.Exclamation, " Error") ' Else ' MsgBox("Successfully downloaded file!", MsgBoxStyle.OKOnly Or MsgBoxStyle.Information, " ") ' End If ' m_objDownload = Nothing ' End Sub ' Private Sub m_objDownload_Progress(ByVal lngMin As Long, ByVal lngMax As Long, ByVal lngValue As Long, ByVal lngBytesLeft As Long, ByVal dblBytesPerSecond As Double, ByVal dblSecondsLeft As Double) Handles m_objDownload.DownloadProgress ' With picProgress ' .Minimum = lngMin ' .Maximum = lngMax ' .Value = lngValue ' .Refresh() ' End With ' Me.Text = lngValue & " / " & lngMax & " - " & lngBytesLeft & " Left [" & dblSecondsLeft & " Seconds Left] [" & CSng(dblBytesPerSecond / 1024) & " KB / Sec]" ' End Sub ' '============================================================================================================= Imports System Imports Microsoft.VisualBasic Imports System.Windows.Forms Public Class cDownload #Region "Local Variable Declarations" Private m_blnCancel As Boolean Private m_ServerAddress As String Private m_LocalDirectory As String Private m_BufferSize As Integer Private m_RequestMethod As String Private m_Timeout As Integer Private m_OverwriteIfExists As Boolean Private m_ProxyAddress As String Private m_ProxyPort As Integer Private m_ProxyName As String Private m_ProxyPass As String Private m_ProxyBypassForLocal As Boolean Private m_ProxyBypassList() As String #End Region #Region "Public Event Declarations" ' If failed to get the total length of the file to download... lngMax, lngBytesLeft, and dblSecondsLeft will always be set to (-1) Public Event DownloadProgress(ByVal lngMin As Long, ByVal lngMax As Long, ByVal lngValue As Long, ByVal lngBytesLeft As Long, ByVal dblBytesPerSecond As Double, ByVal dblSecondsLeft As Double) #End Region #Region "Public Constructors" Public Sub New(Optional ByVal strServerAddress As String = "", _ Optional ByVal strLocalDirectory As String = "C:\", _ Optional ByVal strProxyAddress As String = "", _ Optional ByVal intProxyPort As Integer = 80, _ Optional ByVal strProxyName As String = "", _ Optional ByVal strProxyPassword As String = "", _ Optional ByVal blnBypassProxyForLocal As Boolean = True) m_ServerAddress = Trim(strServerAddress) m_LocalDirectory = Trim(strLocalDirectory) m_ProxyAddress = Trim(strProxyAddress) m_ProxyPort = intProxyPort m_ProxyName = Trim(strProxyName) m_ProxyPass = Trim(strProxyPassword) m_ProxyBypassForLocal = blnBypassProxyForLocal m_BufferSize = 1024 * 4 '4 KB chunks m_OverwriteIfExists = True m_RequestMethod = "GET" m_Timeout = 100000 If m_LocalDirectory <> "" Then m_LocalDirectory = Replace(m_LocalDirectory, "/", "\") If Right(m_LocalDirectory, 1) <> "\" Then m_LocalDirectory = m_LocalDirectory & "\" End If If m_ServerAddress <> "" Then m_ServerAddress = Replace(m_ServerAddress, "\", "/") If Right(m_ServerAddress, 1) <> "/" Then m_ServerAddress = m_ServerAddress & "/" If InStr(m_ServerAddress, "://") < 1 Then m_ServerAddress = "http://" & m_ServerAddress End If If m_ProxyAddress <> "" Then m_ProxyAddress = Replace(m_ProxyAddress, "\", "/") If InStr(m_ProxyAddress, "://") < 1 Then m_ProxyAddress = "http://" & m_ProxyAddress End If End Sub #End Region #Region "Public Deconstructors" Protected Overrides Sub Finalize() Erase m_ProxyBypassList MyBase.Finalize() End Sub #End Region #Region "Public Property Declarations" Public Property RemoteDirectoryPath() As String Get Return m_ServerAddress End Get Set(ByVal Value As String) m_ServerAddress = Value If m_ServerAddress <> "" Then m_ServerAddress = Replace(m_ServerAddress, "\", "/") If Right(m_ServerAddress, 1) <> "/" Then m_ServerAddress = m_ServerAddress & "/" If InStr(m_ServerAddress, "://") < 1 Then m_ServerAddress = "http://" & m_ServerAddress End If End Set End Property Public Property LocalDirectoryPath() As String Get Return m_LocalDirectory End Get Set(ByVal Value As String) m_LocalDirectory = Value If m_LocalDirectory <> "" Then m_LocalDirectory = Replace(m_LocalDirectory, "/", "\") If Right(m_LocalDirectory, 1) <> "\" Then m_LocalDirectory = m_LocalDirectory & "\" End If End Set End Property Public Property BufferSize() As Integer Get Return m_BufferSize End Get Set(ByVal Value As Integer) If Value > 0 Then m_BufferSize = Value Else m_BufferSize = 1 End If End Set End Property Public Property OverwriteIfFilesExist() As Boolean Get Return m_OverwriteIfExists End Get Set(ByVal Value As Boolean) m_OverwriteIfExists = Value End Set End Property Public Property RequestMethod() As String Get Return m_RequestMethod End Get Set(ByVal Value As String) m_RequestMethod = Value End Set End Property Public Property TimeOut() As Integer Get Return m_Timeout End Get Set(ByVal Value As Integer) If Value > 0 Then m_Timeout = Value Else m_Timeout = 1 End If End Set End Property Public Property ProxyAddress() As String Get Return m_ProxyAddress End Get Set(ByVal Value As String) m_ProxyAddress = Value If m_ProxyAddress <> "" Then m_ProxyAddress = Replace(m_ProxyAddress, "\", "/") If InStr(m_ProxyAddress, "://") < 1 Then m_ProxyAddress = "http://" & m_ProxyAddress End If End Set End Property Public Property ProxyPort() As Integer Get Return m_ProxyPass End Get Set(ByVal Value As Integer) If Value >= 0 Then m_ProxyPort = Value Else m_ProxyPort = 80 End If End Set End Property Public Property ProxyName() As String Get Return m_ProxyName End Get Set(ByVal Value As String) m_ProxyName = Value End Set End Property Public Property ProxyPassword() As String Get Return m_ProxyPass End Get Set(ByVal Value As String) m_ProxyPass = Value End Set End Property Public Property ProxyBypassForLocal() As Boolean Get Return m_ProxyBypassForLocal End Get Set(ByVal Value As Boolean) m_ProxyBypassForLocal = Value End Set End Property #End Region #Region "Public Method Declarations" Public Sub CancelDownload() m_blnCancel = True Application.DoEvents() End Sub Public Overloads Function DownloadFile(ByVal strLocalFilePath As String, _ ByVal strRemoteFilePath As String, _ ByVal blnOverwriteIfExists As Boolean, _ Optional ByVal intTimeOut As Integer = 100000, _ Optional ByRef Return_ErrNum As Integer = 0, _ Optional ByRef Return_ErrSrc As String = "", _ Optional ByRef Return_ErrDesc As String = "") As Boolean m_OverwriteIfExists = blnOverwriteIfExists m_Timeout = intTimeOut Return DownloadFile(strLocalFilePath, strRemoteFilePath, "", "", Return_ErrNum, Return_ErrSrc, Return_ErrDesc) End Function Public Overloads Function DownloadFile(ByVal strLocalFilePath As String, _ ByVal strRemoteFilePath As String, _ Optional ByRef Return_ErrNum As Integer = 0, _ Optional ByRef Return_ErrSrc As String = "", _ Optional ByRef Return_ErrDesc As String = "") As Boolean Return DownloadFile(strLocalFilePath, strRemoteFilePath, "", "", Return_ErrNum, Return_ErrSrc, Return_ErrDesc) End Function Public Overloads Function DownloadFile(ByVal strLocalFilePath As String, _ ByVal strRemoteFilePath As String, _ ByVal strPageAuthName As String, _ ByVal strPageAuthPassword As String, _ Optional ByRef Return_ErrNum As Integer = 0, _ Optional ByRef Return_ErrSrc As String = "", _ Optional ByRef Return_ErrDesc As String = "") As Boolean On Error GoTo ErrorTrap Dim sLocalFile As String Dim sLocalPath As String Dim sRemoteFile As String Dim sRemotePath As String Dim bReturn As Boolean ' Set default values Return_ErrNum = 0 Return_ErrSrc = "" Return_ErrDesc = "" ' Get the file information strLocalFilePath = Trim(Replace(strLocalFilePath, "/", "\")) sLocalFile = Right(strLocalFilePath, Len(strLocalFilePath) - InStrRev(strLocalFilePath, "\")) sLocalPath = Left(strLocalFilePath, Len(strLocalFilePath) - Len(sLocalFile)) strRemoteFilePath = Trim(Replace(strRemoteFilePath, "\", "/")) sRemoteFile = Right(strRemoteFilePath, Len(strRemoteFilePath) - InStrRev(strRemoteFilePath, "/")) sRemotePath = Left(strRemoteFilePath, Len(strRemoteFilePath) - Len(sRemoteFile)) m_ServerAddress = sRemotePath m_LocalDirectory = sLocalPath bReturn = DownloadFile(sRemoteFile, strPageAuthName, strPageAuthPassword, Return_ErrNum, Return_ErrSrc, Return_ErrDesc) If UCase(sLocalFile) <> UCase(sRemoteFile) Then IO.File.Move(sLocalPath & sRemoteFile, sLocalPath & sLocalFile) End If Return bReturn ErrorTrap: Return_ErrNum = Err.Number Return_ErrSrc = Err.Source Return_ErrDesc = Err.Description Err.Clear() Return False End Function ' Download the specified file Public Overloads Function DownloadFile(ByVal strFileName As String, _ ByVal strPageAuthName As String, _ ByVal strPageAuthPassword As String, _ Optional ByRef Return_ErrNum As Integer = 0, _ Optional ByRef Return_ErrSrc As String = "", _ Optional ByRef Return_ErrDesc As String = "") As Boolean On Error GoTo ErrorTrap Dim oWebRequest As Net.WebRequest Dim oWebResponse As Net.WebResponse Dim oWebProxy As Net.WebProxy Dim oResponseStream As IO.Stream Dim oFileStream As IO.FileStream Dim abytBuffer(m_BufferSize) As Byte Dim lngBytesRead As Long Dim lngTotalBytesRead As Long Dim lngTotalBytes As Long Dim strRemotePath As String Dim strLocalPath As String Dim strTemp As String Dim Time_Start As Double Dim Time_Seconds As Long ' Set default values Return_ErrNum = 0 Return_ErrSrc = "" Return_ErrDesc = "" m_blnCancel = False ' Validate parameters strFileName = Trim(strFileName) m_ServerAddress = Trim(m_ServerAddress) m_LocalDirectory = Trim(m_LocalDirectory) If m_ServerAddress = "" Then Err.Raise(-1, "cDownload >> DownloadFile", "No server address specified to download from") ElseIf strFileName = "" Then Err.Raise(-1, "cDownload >> DownloadFile", "No file specified to download") ElseIf m_LocalDirectory = "" Then Err.Raise(-1, "cDownload >> DownloadFile", "No local path specified to save to") End If m_ServerAddress = Replace(m_ServerAddress, "\", "/") If Right(m_ServerAddress, 1) <> "/" Then m_ServerAddress = m_ServerAddress & "/" m_LocalDirectory = Replace(m_LocalDirectory, "/", "\") If Right(m_LocalDirectory, 1) <> "\" Then m_LocalDirectory = m_LocalDirectory & "\" If Left(strFileName, 1) = "\" Or Left(strFileName, 1) = "/" Then strFileName = Right(strFileName, Len(strFileName) - 1) ' Get the remote and local paths strRemotePath = m_ServerAddress & strFileName strLocalPath = m_LocalDirectory & strFileName ' Make sure the local directory exists If IO.Directory.Exists(m_LocalDirectory) = False Then IO.Directory.CreateDirectory(m_LocalDirectory) ' If the file exists and the user specified NOT to overwrite it, error out If m_OverwriteIfExists = False And IO.File.Exists(strLocalPath) = True Then Err.Raise(58, "cDownload >> DownloadFile", "File already exists") ElseIf IO.File.Exists(strLocalPath) = True Then IO.File.Delete(strLocalPath) End If ' Create a WebRequest object to work with oWebRequest = Net.WebRequest.Create(strRemotePath) oWebRequest.Method = m_RequestMethod oWebRequest.Timeout = m_Timeout oWebRequest.Headers.Add("Pragma", "no-cache") oWebRequest.Headers.Add("Cache-Control", "no-cache, no-store, max-age=0") oWebRequest.Headers.Add("Expires", "Mon, 26 Jul 1997 05:00:00 GMT") ' Setup the proxy and credentials to work with If m_ProxyAddress <> "" Then oWebProxy = New Net.WebProxy(m_ProxyAddress & ":" & m_ProxyPort.ToString, m_ProxyBypassForLocal) If m_ProxyName <> "" Or m_ProxyPass <> "" Then oWebProxy.Credentials = New Net.NetworkCredential(m_ProxyName, m_ProxyPass) End If oWebRequest.Proxy = oWebProxy End If If strPageAuthName <> "" Or strPageAuthPassword <> "" Then oWebRequest.Credentials = New Net.NetworkCredential(strPageAuthName, strPageAuthPassword) End If ' Get the response from the server oWebResponse = oWebRequest.GetResponse strTemp = Trim(oWebResponse.Headers("Content-Length")) If strTemp <> "" And IsNumeric(strTemp) = True Then lngTotalBytes = CLng(strTemp) Else lngTotalBytes = -1 End If oResponseStream = oWebResponse.GetResponseStream ' Create the file and get a reference to it's stream oFileStream = New IO.FileStream(strLocalPath, IO.FileMode.OpenOrCreate, IO.FileAccess.Write, IO.FileShare.None) ' Download the file a buffer at a time and report progress Time_Start = Microsoft.VisualBasic.Timer() + 1 lngBytesRead = oResponseStream.Read(abytBuffer, 0, m_BufferSize) Do While lngBytesRead > 0 And m_blnCancel = False lngTotalBytesRead = lngTotalBytesRead + lngBytesRead oFileStream.Write(abytBuffer, 0, lngBytesRead) Application.DoEvents() If Time_Start <= Microsoft.VisualBasic.Timer() Then Time_Seconds = Time_Seconds + 1 Time_Start = Microsoft.VisualBasic.Timer() + 1 End If If lngTotalBytes <> -1 Then If Time_Seconds > 0 Then RaiseEvent DownloadProgress(0, lngTotalBytes, lngTotalBytesRead, (lngTotalBytes - lngTotalBytesRead), (lngTotalBytesRead / Time_Seconds), (lngTotalBytes / (lngTotalBytesRead / Time_Seconds)) - Time_Seconds) Else RaiseEvent DownloadProgress(0, lngTotalBytes, lngTotalBytesRead, (lngTotalBytes - lngTotalBytesRead), 0, 0) End If Else If Time_Seconds > 0 Then RaiseEvent DownloadProgress(0, -1, lngTotalBytesRead, -1, (lngTotalBytesRead / Time_Seconds), -1) Else RaiseEvent DownloadProgress(0, -1, lngTotalBytesRead, -1, 0, -1) End If End If lngBytesRead = oResponseStream.Read(abytBuffer, 0, m_BufferSize) Loop ' Cancel the download if told to do so If m_blnCancel = True Then oWebResponse.Close() ' Close the response stream oResponseStream.Close() oResponseStream = Nothing ' Write the data to file and close the file oFileStream.Flush() oFileStream.Close() oFileStream = Nothing ' Set the date on the downloaded file to the date of the source If m_blnCancel = False Then IO.File.SetLastWriteTime(strLocalPath, oWebResponse.Headers("Last-Modified")) ' Close the response object If m_blnCancel = False Then oWebResponse.Close() oWebResponse = Nothing Return True ErrorTrap: Return_ErrNum = Err.Number Return_ErrSrc = Err.Source Return_ErrDesc = Err.Description Err.Clear() If Not oFileStream Is Nothing Then oFileStream.Flush() oFileStream.Close() oFileStream = Nothing End If If Not oWebResponse Is Nothing Then oWebResponse.Close() oWebResponse = Nothing End If oWebRequest = Nothing Return False End Function #End Region End Class