Option Explicit On
Option Strict On
Imports System
Imports System.Net
Imports System.Text
Public Class DownloadWorker
Private _size As Long
Private mRead As Long
Private _status As DownLoadStatus
Private _errorDescription As String
Private _sourceURL As String
Private _destPath As String
Private _referer As String
Public Sub New()
MyBase.new()
_status = DownLoadStatus.Idle
End Sub
Public Sub New(ByVal sSourceURL As String, ByVal sDestPath As String)
MyBase.new()
_sourceURL = sSourceURL
_destPath = sDestPath
End Sub
Public Sub New(ByVal sSourceURL As String, ByVal sDestPath As String, ByVal sReferer As String)
MyBase.new()
_sourceURL = sSourceURL
_destPath = sDestPath
_referer = sReferer
End Sub
Public Enum DownLoadStatus
Idle = 0
Connecting = 1
Connected = 2
Downloading = 3
Completed = 4
ErrorOccured = 5
End Enum
Public Event StatusChanged(ByRef sender As DownloadWorker, ByVal OldStatus As DownLoadStatus, ByVal NewStatus As DownLoadStatus)
Public Event ProgressChanged(ByRef sender As DownloadWorker)
Public Property SourceURL() As String
Get
Return _sourceURL
End Get
Set(ByVal Value As String)
Select Case _status
Case DownLoadStatus.Connected, DownLoadStatus.Connecting, DownLoadStatus.Downloading
Throw New InvalidOperationException("SourceURL cannot be changed while download is in progress")
Case Else
_sourceURL = Value
End Select
End Set
End Property
Public Property DestPath() As String
Get
Return _destPath
End Get
Set(ByVal Value As String)
Select Case _status
Case DownLoadStatus.Connected, DownLoadStatus.Connecting, DownLoadStatus.Downloading
Throw New InvalidOperationException("Destination Path cannot be changed while download is in progress")
Case Else
_destPath = Value
End Select
End Set
End Property
Public Property Referer() As String
Get
Return _referer
End Get
Set(ByVal Value As String)
Select Case _status
Case DownLoadStatus.Connected, DownLoadStatus.Connecting, DownLoadStatus.Downloading
Throw New InvalidOperationException("Referer cannot be changed while download is in progress")
Case Else
_referer = Value
End Select
End Set
End Property
Public ReadOnly Property Status() As DownLoadStatus
Get
Return _status
End Get
End Property
Public ReadOnly Property Progress() As Double
Get
If _size = 0 Then
Return 0
Else
Return mRead / _size
End If
End Get
End Property
Public ReadOnly Property Size() As Long
Get
Return _size
End Get
End Property
Public ReadOnly Property Downloaded() As Long
Get
Return mRead
End Get
End Property
Public ReadOnly Property ErrorDescription() As String
Get
Return _errorDescription
End Get
End Property
Private Sub ChangeStatus(ByVal NewStatus As DownLoadStatus)
Dim Temp As DownLoadStatus
Temp = _status
_status = NewStatus
RaiseEvent StatusChanged(Me, Temp, NewStatus)
End Sub
Public Sub DownloadFile()
Dim bBuffer() As Byte
Const BlockSize As Integer = 4096
Dim iRead As Integer
Dim iReadTotal As Integer
Dim iTotalSize As Integer
If _sourceURL = "" Then
Throw New InvalidOperationException("No Source URL specified")
Exit Sub
End If
If _destPath = "" Then
Throw New InvalidOperationException("No Destination Path specified")
Exit Sub
End If
Try
Call ChangeStatus(DownLoadStatus.Connecting)
Dim wr As HttpWebRequest = CType(WebRequest.Create(_sourceURL), HttpWebRequest)
If _referer <> "" Then
wr.Referer = _referer
End If
Dim resp As HttpWebResponse = CType(wr.GetResponse(), HttpWebResponse)
_size = resp.ContentLength
Call ChangeStatus(DownLoadStatus.Connected)
Dim sIn As IO.Stream = resp.GetResponseStream
Dim sOut As New IO.FileStream(_destPath, IO.FileMode.Create)
ReDim bBuffer(BlockSize - 1)
Call ChangeStatus(DownLoadStatus.Downloading)
iRead = sIn.Read(bBuffer, 0, BlockSize)
mRead = iRead
While iRead > 0
RaiseEvent ProgressChanged(Me)
sOut.Write(bBuffer, 0, iRead)
iRead = sIn.Read(bBuffer, 0, BlockSize)
mRead += iRead
End While
sIn.Close()
sOut.Close()
Call ChangeStatus(DownLoadStatus.Completed)
Catch ex As Exception
_errorDescription = ex.Message
Call ChangeStatus(DownLoadStatus.ErrorOccured)
End Try
End Sub
End Class