Download File calculating speed and progress -Background Worker & Progress bar

February 13, 2009 by AcidRaZor · Leave a Comment
Filed under: .NET, Programming 101 

Here is some code that will make use of VB.NET’s Backgroundworker class and initiate a web request to download a file. It will calculate the file’s speed as well as indicate it’s progress on a progress bar. All the while keeping the Main Form available.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
Dim whereToSave As String 'Where the program save the file
 
    Delegate Sub ChangeTextsSafe(ByVal length As Long, ByVal position As Integer, ByVal percent As Integer, ByVal speed As Double)
    Delegate Sub DownloadCompleteSafe(ByVal cancelled As Boolean)
 
    Public Sub DownloadComplete(ByVal cancelled As Boolean)
        Me.txtFileName.Enabled = True
        Me.btnDownload.Enabled = True
        Me.btnCancel.Enabled = False
 
        If cancelled Then
 
            Me.Label4.Text = "Cancelled"
 
            'MessageBox.Show("Download aborted", "Aborted", MessageBoxButtons.OK, MessageBoxIcon.Information)
 
 
        Else
            Me.Label4.Text = "Successfully downloaded"
 
            'MessageBox.Show("Successfully downloaded!", "All OK", MessageBoxButtons.OK, MessageBoxIcon.Information)
 
        End If
 
        Me.ProgressBar1.Value = 0
        Me.Label5.Text = "Downloading: "
        Me.Label6.Text = "Save to: "
        Me.Label3.Text = "File size: "
        Me.Label2.Text = "Download speed: "
        Me.Label4.Text = ""
 
    End Sub
 
    Public Sub ChangeTexts(ByVal length As Long, ByVal position As Integer, ByVal percent As Integer, ByVal speed As Double)
 
        Me.Label3.Text = "File size: " & Math.Round((length / 1024), 2) & " KB"
 
        Me.Label5.Text = "Downloading: " & Me.txtFileName.Text
 
        Me.Label4.Text = "Downloaded " & Math.Round((position / 1024), 2) & " KB of " & Math.Round((length / 1024), 2) & "KB (" & Me.ProgressBar1.Value & "%)"
 
        If speed = -1 Then
            Me.Label2.Text = "Download speed: calculating..."
        Else
            Me.Label2.Text = "Download speed: " & Math.Round((speed / 1024), 2) & " KB/s"
        End If
 
        Me.ProgressBar1.Value = percent
 
 
    End Sub
 
    Private Sub btnDownload_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnDownload.Click
        If Me.txtFileName.Text <> "" AndAlso Me.txtFileName.Text.StartsWith("http://") Then
 
 
            Me.SaveFileDialog1.FileName = Me.txtFileName.Text.Split("/"c)(Me.txtFileName.Text.Split("/"c).Length - 1)
 
            If Me.SaveFileDialog1.ShowDialog = Windows.Forms.DialogResult.OK Then
 
                Me.whereToSave = Me.SaveFileDialog1.FileName
 
                Me.SaveFileDialog1.FileName = ""
 
                Me.Label6.Text = "Save to: " & Me.whereToSave
 
                Me.txtFileName.Enabled = False
                Me.btnDownload.Enabled = False
                Me.btnCancel.Enabled = True
 
                Me.BackgroundWorker1.RunWorkerAsync() 'Start download
 
            End If
 
        Else
 
            MessageBox.Show("Please insert valid URL for download", "Warning", MessageBoxButtons.OK, MessageBoxIcon.Warning)
 
        End If
    End Sub
 
    Private Sub btnCancel_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnCancel.Click
        Me.BackgroundWorker1.CancelAsync() 'Send cancel request
        Try
            Me.bckZip.CancelAsync()
        Catch ex As Exception
            'Do Nothing
        End Try
    End Sub
 
    Private Sub BackgroundWorker1_DoWork(ByVal sender As System.Object, ByVal e As System.ComponentModel.DoWorkEventArgs) Handles BackgroundWorker1.DoWork
 
        'Creating the request and getting the response
        Dim theResponse As HttpWebResponse
        Dim theRequest As HttpWebRequest
        Try 'Checks if the file exist
 
            theRequest = WebRequest.Create(Me.txtFileName.Text)
            theResponse = theRequest.GetResponse
            theRequest.Timeout = 10000000
        Catch ex As Exception
 
            MessageBox.Show("An error occurred while downloading file. Possibe causes:" & ControlChars.CrLf & _
                            "1) File doesn't exist" & ControlChars.CrLf & _
                            "2) Remote server error", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error)
 
            Dim cancelDelegate As New DownloadCompleteSafe(AddressOf DownloadComplete)
 
            Me.Invoke(cancelDelegate, True)
 
            Exit Sub
        End Try
        Dim length As Long = theResponse.ContentLength 'Size of the response (in bytes)
 
        Dim safedelegate As New ChangeTextsSafe(AddressOf ChangeTexts)
        Me.Invoke(safedelegate, length, 0, 0, 0) 'Invoke the TreadsafeDelegate
 
        Dim writeStream As New IO.FileStream(Me.whereToSave, IO.FileMode.Create)
 
        'Replacement for Stream.Position (webResponse stream doesn't support seek)
        Dim nRead As Integer
 
        'To calculate the download speed
        Dim speedtimer As New Stopwatch
        Dim currentspeed As Double = -1
        Dim readings As Integer = 0
 
        Do
 
            If BackgroundWorker1.CancellationPending Then 'If user abort download
                Exit Do
            End If
 
            speedtimer.Start()
 
            Dim readBytes(4096) As Byte
            Dim bytesread As Integer = theResponse.GetResponseStream.Read(readBytes, 0, 4096)
 
            nRead += bytesread
            Dim percent As Integer = (nRead / length) * 100
 
            Me.Invoke(safedelegate, length, nRead, percent, currentspeed)
 
            If bytesread = 0 Then Exit Do
 
            writeStream.Write(readBytes, 0, bytesread)
 
            speedtimer.Stop()
 
            readings += 1
            If readings >= 5 Then 'For increase precision, the speed it's calculated only every five cicles
                currentspeed = 20480 / (speedtimer.ElapsedMilliseconds / 1000)
                speedtimer.Reset()
                readings = 0
            End If
        Loop
 
        'Close the streams
        theResponse.GetResponseStream.Close()
        writeStream.Close()
 
        If Me.BackgroundWorker1.CancellationPending Then
 
            IO.File.Delete(Me.whereToSave)
 
            Dim cancelDelegate As New DownloadCompleteSafe(AddressOf DownloadComplete)
 
            Me.Invoke(cancelDelegate, True)
 
            Exit Sub
 
        End If
 
        Dim completeDelegate As New DownloadCompleteSafe(AddressOf DownloadComplete)
 
        Me.Invoke(completeDelegate, False)
 
    End Sub

SEO Powered by Platinum SEO from Techblissonline