Answered by:
Multiple File Download simultaneously

Question
-
I have a class that uses a BackGroundWorker to download a single file using HttpWebRequest and HttpWebResponse
Downloading single file works.
But if I make two objects of that class and start downloading 2 different files simultaneously, there is nothing produced. Execution exits after getResponse() without any error or exception.
Is there any way to achieve simultaneous file download?
Monday, May 23, 2011 6:33 PM
Answers
-
Put a button and 2 long textboxes on Form1 of a new Windows Forms Application.
Replace the Form1 code with:
Imports System.Net
Imports System.ComponentModel
Public Class Form1
Dim WCs As New List(Of WebClient)
Private Sub Button1_Click(ByVal sender As Object, _
ByVal e As EventArgs) Handles Button1.Click
WCs.Add(New WebClient)
WCs.Add(New WebClient)
AddHandler WCs(0).DownloadFileCompleted, AddressOf WC_DownloadFileComplete
AddHandler WCs(1).DownloadFileCompleted, AddressOf WC_DownloadFileComplete
AddHandler WCs(0).DownloadProgressChanged, AddressOf WC_ProgressChanged
AddHandler WCs(1).DownloadProgressChanged, AddressOf WC_ProgressChanged
WCs(0).DownloadFileAsync(New Uri("http://www.fileden.com/files/2010/2/15/2761729/Cppup/Setup.rar"), "r1.rar")
WCs(1).DownloadFileAsync(New Uri("http://www.fileden.com/files/2010/2/15/2761729/SoftwaresZoo/SZTUT.rar"), "r2.rar")
End Sub
Sub WC_ProgressChanged(ByVal sender As Object, ByVal e As DownloadProgressChangedEventArgs)
Dim WC As WebClient = DirectCast(sender, WebClient)
Dim Text As String = e.BytesReceived.ToString + " Bytes of " + e.TotalBytesToReceive.ToString + " downloaded of file "
If WCs.IndexOf(WC) = 0 Then TextBox1.Text = Text + "r1.rar" Else TextBox2.Text = Text + "r2.rar"
End Sub
Sub WC_DownloadFileComplete(ByVal sender As Object, ByVal e As AsyncCompletedEventArgs)
Dim WC As WebClient = DirectCast(sender, WebClient)
Dim Text As String = " download completed"
If WCs.IndexOf(WC) = 0 Then TextBox1.Text = "r1.rar" + Text Else TextBox2.Text = "r2.rar" + Text
WCs.Remove(WC)
WC.Dispose()
End Sub
End Class
- Proposed as answer by Mike FengModerator Wednesday, May 25, 2011 9:43 AM
- Marked as answer by Mike FengModerator Thursday, June 2, 2011 9:59 AM
Tuesday, May 24, 2011 9:57 AM
All replies
-
Is there any way to achieve simultaneous file download?
It's done all the time. Something's wrong with your code.Monday, May 23, 2011 7:25 PM -
Alright it worked for other URLs, but why it failed for these 2 URLs of same server:-
http://www.fileden.com/files/2010/2/15/2761729/SoftwaresZoo/SZTUT.rar
http://www.fileden.com/files/2010/2/15/2761729/Cppup/Setup.rar
Can be downloaded successfully individually but not simultaneously, execution exits after -
webResp = CType(webReq.GetResponse, HttpWebResponse) 'Without any exception
Tuesday, May 24, 2011 6:03 AM -
Alright it worked for other URLs, but why it failed for these 2 URLs of same server:-
http://www.fileden.com/files/2010/2/15/2761729/SoftwaresZoo/SZTUT.rar
http://www.fileden.com/files/2010/2/15/2761729/Cppup/Setup.rar
Can be downloaded successfully individually but not simultaneously, execution exits after -
webResp = CType(webReq.GetResponse, HttpWebResponse) 'Without any exception
I have no problem downloading both files simultaneously in IE9.Tuesday, May 24, 2011 6:12 AM -
This is the code
Imports System.ComponentModel Imports System.IO Imports System.Net Public Class DownloadFile Public Event OnError(ByVal s As Object, ByVal e As ErrorEventArgs) Public Event ProgressChanged(ByVal s As Object, ByVal e As EventArgs) Public Event DownloadCompleted(ByVal s As Object, ByVal e As EventArgs) #Region "Data Members" Private WithEvents bw As New BackgroundWorker Private trigger As New Threading.ManualResetEvent(True) Private _file As FileInfo, _PackageSize As Int32, _FileProgress As Long, _currentSpeed As Long, _stopWatchCycles As Int32, _busy As Boolean, _paused As Boolean, _lastSize As Long #End Region Public Class ErrorEventArgs : Inherits System.EventArgs Public exception As Exception Public Sub New(ByVal ex As String) exception = New Exception(ex) End Sub Public Sub New(ByVal ex As Exception) exception = ex End Sub End Class Public Sub New() bw.WorkerReportsProgress = True bw.WorkerSupportsCancellation = True _PackageSize = 4096 _stopWatchCycles = 50 _paused = False _busy = False End Sub Public Class FileInfo Public Path As String Public Name As String Public URL As String Public ReadOnly Property FileLen() As Long Get Try Return My.Computer.FileSystem.GetFileInfo(Path).Length Catch ex As Exception Return CType(TotalLength, Long) End Try End Get End Property Public Directory As String Public TotalLength As String Public Sub New(ByVal path As String, ByVal _url As String) URL = _url Me.Path = path Me.Name = Me.Path.Split("\"c)(Me.Path.Split("\"c).Length - 1) Directory = Me.Path.Replace(Me.Name, "").Trim TotalLength = "0" End Sub Public Sub New(ByRef cdb As Database, ByVal row As Integer) URL = cdb.table(0)(1)(row) Me.Path = cdb.table(0)(0)(row) Me.Name = cdb.table(0)(0)(row).Split("\"c)(cdb.table(0)(0)(row).Split("\"c).Length - 1) Directory = Me.Path.Replace(Me.Name, "").Trim TotalLength = cdb.table(0)(2)(row) End Sub End Class Private Enum [Event] ProgressChanged = 0 DownloadCompleted = 1 ErrorOccured = 2 End Enum Public Property File() As FileInfo Get Return _file End Get Set(ByVal value As FileInfo) _file = value End Set End Property Public Property PackageSize() As Int32 Get Return _PackageSize End Get Set(ByVal value As Integer) If (value > 0) Then _PackageSize = value Else Throw New InvalidOperationException("Package Size must be > 0") End If End Set End Property Public Property StopWatchCyclesAmount() As Int32 Get Return _stopWatchCycles End Get Set(ByVal value As Int32) If value > 0 Then _stopWatchCycles = value Else Throw New InvalidOperationException("The StopWatchCyclesAmount needs to be greather then 0") End If End Set End Property Public Property IsBusy() As Boolean Get Return _busy End Get Set(ByVal value As Boolean) If Me.IsBusy <> value Then _busy = value If Me.IsBusy Then bw.RunWorkerAsync() Else _paused = False bw.CancelAsync() End If End If End Set End Property Public ReadOnly Property Progress() As Integer Get Return ((_FileProgress + _lastSize) * 100) / File.TotalLength End Get End Property Public ReadOnly Property Speed() As Long Get Return _currentSpeed End Get End Property Public ReadOnly Property DownloadSpeed() As String Get Return FormatSizeBinary(Speed) End Get End Property Public Property IsPaused() As Boolean Get Return _paused End Get Set(ByVal value As Boolean) If Me.IsBusy Then If value <> Me.IsPaused Then _paused = value If Me.IsPaused Then trigger.Reset() Else trigger.Set() End If End If End If End Set End Property Public Sub Start() CalculateFSize() _FileProgress = 0 bw.RunWorkerAsync() End Sub Public Sub Pause() IsPaused = True End Sub Public Sub [Resume]() IsPaused = False End Sub Public Shared Function FormatSizeBinary(ByVal size As Int64, Optional ByVal decimals As Int32 = 2) As String ' By De Dauw Jeroen - April 2009 - jeroen_dedauw@yahoo.com Dim sizes() As String = {"B", "KiB", "MiB", "GiB", "TiB", "PiB", "EiB", "ZiB", "YiB"} Dim formattedSize As Double = size Dim sizeIndex As Int32 = 0 While formattedSize >= 1024 And sizeIndex < sizes.Length formattedSize /= 1024 sizeIndex += 1 End While Return Math.Round(formattedSize, decimals).ToString & sizes(sizeIndex) End Function Private Sub CalculateFSize() Try Dim webReq As HttpWebRequest = CType(Net.WebRequest.Create(File.URL), HttpWebRequest) Dim webResp As HttpWebResponse = CType(webReq.GetResponse, HttpWebResponse) File.TotalLength = webResp.ContentLength Catch ex As Exception RaiseEvent OnError(Me, New DownloadFile.ErrorEventArgs(ex)) End Try End Sub Private Sub bw_work(ByVal s As Object, ByVal e As EventArgs) Handles bw.DoWork _busy = True If Not Directory.Exists(File.Directory) Then Directory.CreateDirectory(Me.File.Directory) Dim readBytes(Me.PackageSize - 1) As Byte Dim currentPackageSize As Int32 Dim writer As New FileStream(File.Path, IO.FileMode.Append) Dim speedTimer As New Stopwatch Dim readings As Int32 = 0 Dim webReq As HttpWebRequest Dim webResp As HttpWebResponse Dim size As Int64 = 0 _lastSize = File.FileLen Try webReq = CType(Net.WebRequest.Create(Me.File.URL), HttpWebRequest) If (File.FileLen = 0) Then webResp = CType(webReq.GetResponse, HttpWebResponse) size = webResp.ContentLength File.TotalLength = size.ToString ElseIf File.FileLen = CType(File.TotalLength, Double) Then writer.Close() fireEventFromBgw([Event].ProgressChanged) _busy = False Exit Sub Else webReq.AddRange(CType(File.FileLen, Integer)) webResp = CType(webReq.GetResponse, HttpWebResponse) size = webResp.ContentLength End If Catch ex As Exception Dim ec As New ErrorEventArgs(ex) writer.Close() _busy = False fireEventFromBgw([Event].ErrorOccured, ec) Exit Sub End Try While _FileProgress < size If bw.CancellationPending Then speedTimer.Stop() writer.Close() webResp.Close() _busy = False fireEventFromBgw([Event].ErrorOccured, New ErrorEventArgs("Download Worker Stopped due to external commands")) Exit Sub End If trigger.WaitOne() speedTimer.Start() Try currentPackageSize = webResp.GetResponseStream().Read(readBytes, 0, Me.PackageSize) Catch ex As Exception Dim ec As New ErrorEventArgs(ex) writer.Close() fireEventFromBgw([Event].ErrorOccured, ec) Exit Sub End Try _FileProgress += currentPackageSize fireEventFromBgw([Event].ProgressChanged) writer.Write(readBytes, 0, currentPackageSize) readings += 1 If readings >= Me.StopWatchCyclesAmount Then _currentSpeed = CInt(Me.PackageSize * StopWatchCyclesAmount * 1000 / (speedTimer.ElapsedMilliseconds + 1)) speedTimer.Reset() readings = 0 End If End While fireEventFromBgw([Event].DownloadCompleted) speedTimer.Stop() writer.Close() webResp.Close() _busy = False 'fireEventFromBgw([Event].FileDownloadSucceeded) End Sub Private Sub fireEventFromBgw(ByVal eventName As [Event], Optional ByVal data As Object = Nothing) bw.ReportProgress(eventName, data) End Sub Private Sub bw_prg(ByVal sender As Object, ByVal e As ProgressChangedEventArgs) Handles bw.ProgressChanged Select Case e.ProgressPercentage Case [Event].ProgressChanged RaiseEvent ProgressChanged(Me, New EventArgs) Case [Event].DownloadCompleted RaiseEvent DownloadCompleted(Me, New EventArgs) Case [Event].ErrorOccured RaiseEvent OnError(sender, e.UserState) End Select End Sub End Class
For Main Form --
Where's the problem!<pre lang="x-vbnet"> Private a1 As New DownloadFile, a2 As New DownloadFile Private Sub asd() Handles Me.Load a1.File = New DownloadFile.FileInfo(CurDir() + "\r1.rar", "http://www.fileden.com/files/2010/2/15/2761729/Cppup/Setup.rar") a1.Start() a2.File = New DownloadFile.FileInfo(CurDir() + "\r2.rar", "http://www.fileden.com/files/2010/2/15/2761729/SoftwaresZoo/SZTUT.rar") a2.Start() End Sub
Tuesday, May 24, 2011 6:31 AM -
Put a button and 2 long textboxes on Form1 of a new Windows Forms Application.
Replace the Form1 code with:
Imports System.Net
Imports System.ComponentModel
Public Class Form1
Dim WCs As New List(Of WebClient)
Private Sub Button1_Click(ByVal sender As Object, _
ByVal e As EventArgs) Handles Button1.Click
WCs.Add(New WebClient)
WCs.Add(New WebClient)
AddHandler WCs(0).DownloadFileCompleted, AddressOf WC_DownloadFileComplete
AddHandler WCs(1).DownloadFileCompleted, AddressOf WC_DownloadFileComplete
AddHandler WCs(0).DownloadProgressChanged, AddressOf WC_ProgressChanged
AddHandler WCs(1).DownloadProgressChanged, AddressOf WC_ProgressChanged
WCs(0).DownloadFileAsync(New Uri("http://www.fileden.com/files/2010/2/15/2761729/Cppup/Setup.rar"), "r1.rar")
WCs(1).DownloadFileAsync(New Uri("http://www.fileden.com/files/2010/2/15/2761729/SoftwaresZoo/SZTUT.rar"), "r2.rar")
End Sub
Sub WC_ProgressChanged(ByVal sender As Object, ByVal e As DownloadProgressChangedEventArgs)
Dim WC As WebClient = DirectCast(sender, WebClient)
Dim Text As String = e.BytesReceived.ToString + " Bytes of " + e.TotalBytesToReceive.ToString + " downloaded of file "
If WCs.IndexOf(WC) = 0 Then TextBox1.Text = Text + "r1.rar" Else TextBox2.Text = Text + "r2.rar"
End Sub
Sub WC_DownloadFileComplete(ByVal sender As Object, ByVal e As AsyncCompletedEventArgs)
Dim WC As WebClient = DirectCast(sender, WebClient)
Dim Text As String = " download completed"
If WCs.IndexOf(WC) = 0 Then TextBox1.Text = "r1.rar" + Text Else TextBox2.Text = "r2.rar" + Text
WCs.Remove(WC)
WC.Dispose()
End Sub
End Class
- Proposed as answer by Mike FengModerator Wednesday, May 25, 2011 9:43 AM
- Marked as answer by Mike FengModerator Thursday, June 2, 2011 9:59 AM
Tuesday, May 24, 2011 9:57 AM -
Hi AksHay,
Welcome to the MSDN Forum.
In actrually, it isn't no error, the exception has been handled in the CalculateFSize and bw_work subroutine. So you should step into these two subroutine to see what happened.
In addition, if it is possible, you can take John's ways.
Best regards,
Mike Feng [MSFT]
MSDN Community Support | Feedback to us
Get or Request Code Sample from Microsoft
Please remember to mark the replies as answers if they help and unmark them if they provide no help.
Wednesday, May 25, 2011 10:35 AMModerator