Results 1 to 17 of 17

Thread: how do i make syncronous downloads?

  1. #1

    Thread Starter
    yay gay PT Exorcist's Avatar
    Join Date
    Apr 2002
    Location
    . . . my reason of shame
    Posts
    2,729

    how do i make syncronous downloads?

    i searched for code to download files with vb.net...i came out with this:


    string remoteUri = "http://www.contoso.com/library/homepage/images/";
    string fileName = "ms-banner.gif", myStringWebResource = null;
    // Create a new WebClient instance.
    WebClient myWebClient = new WebClient();
    // Concatenate the domain with the Web resource filename.
    myStringWebResource = remoteUri + fileName;
    listBox1.Items.Add("Downloading File "+fileName.ToString()+" from "+myStringWebResource.ToString()+" ....");
    // Download the Web resource and save it into the current filesystem folder.
    myWebClient.DownloadFile(myStringWebResource,fileName);
    listBox1.Items.Add("Successfully Downloaded File "+fileName.ToString() +" from "+myStringWebResource.ToString());
    listBox1.Items.Add("Downloaded file saved in the following file system folder:");
    listBox1.Items.Add(Application.StartupPath.ToString() );


    it's in C#, but no problem, i can turn it into VB easyly...the problem is that the program freezes while downloading...how do i download files without the all program freezes while downloading...?

  2. #2
    hellswraith
    Guest
    Look up multithreading in the MSDN Library...

    Awe, what the hell, I got some time, here is the link...
    http://www.msdn.microsoft.com/librar...ingExample.asp

  3. #3
    old fart Frans C's Avatar
    Join Date
    Oct 1999
    Location
    the Netherlands
    Posts
    2,926
    I wrote a class for downloading a file in a seperate thread, but i have got the code at home, and I am at work right now.
    I didn't use the DownloadFile method of the WebClient class, because I would like to monitor the progress made.
    I will post it as soon as I get home (in about 8 hours).

  4. #4
    old fart Frans C's Avatar
    Join Date
    Oct 1999
    Location
    the Netherlands
    Posts
    2,926
    OK, here we go.

    The downloadworker class is designed to run in a seperate thread.
    So create a new object of this class. Set some properties (if not provided while creating the object) and start a new thread at the DownloadFile method. The thread will die as soon as the download is complete or fails.

    Be aware that the class is designed for one thread for one object, so if you want to download multiple files at the same time, you need to create multiple objects.

    First the code for the class:

    VB Code:
    1. Option Explicit On
    2. Option Strict On
    3.  
    4. Imports System
    5. Imports System.Net
    6. Imports System.Text
    7.  
    8. Public Class DownloadWorker
    9.     Private _size As Long
    10.     Private mRead As Long
    11.     Private _status As DownLoadStatus
    12.     Private _errorDescription As String
    13.     Private _sourceURL As String
    14.     Private _destPath As String
    15.     Private _referer As String
    16.     Public Sub New()
    17.         MyBase.new()
    18.         _status = DownLoadStatus.Idle
    19.     End Sub
    20.     Public Sub New(ByVal sSourceURL As String, ByVal sDestPath As String)
    21.         MyBase.new()
    22.         _sourceURL = sSourceURL
    23.         _destPath = sDestPath
    24.     End Sub
    25.     Public Sub New(ByVal sSourceURL As String, ByVal sDestPath As String, ByVal sReferer As String)
    26.         MyBase.new()
    27.         _sourceURL = sSourceURL
    28.         _destPath = sDestPath
    29.         _referer = sReferer
    30.     End Sub
    31.  
    32.     Public Enum DownLoadStatus
    33.         Idle = 0
    34.         Connecting = 1
    35.         Connected = 2
    36.         Downloading = 3
    37.         Completed = 4
    38.         ErrorOccured = 5
    39.     End Enum
    40.  
    41.     Public Event StatusChanged(ByRef sender As DownloadWorker, ByVal OldStatus As DownLoadStatus, ByVal NewStatus As DownLoadStatus)
    42.     Public Event ProgressChanged(ByRef sender As DownloadWorker)
    43.     Public Property SourceURL() As String
    44.         Get
    45.             Return _sourceURL
    46.         End Get
    47.         Set(ByVal Value As String)
    48.             Select Case _status
    49.                 Case DownLoadStatus.Connected, DownLoadStatus.Connecting, DownLoadStatus.Downloading
    50.                     Throw New InvalidOperationException("SourceURL cannot be changed while download is in progress")
    51.                 Case Else
    52.                     _sourceURL = Value
    53.             End Select
    54.         End Set
    55.     End Property
    56.     Public Property DestPath() As String
    57.         Get
    58.             Return _destPath
    59.         End Get
    60.         Set(ByVal Value As String)
    61.             Select Case _status
    62.                 Case DownLoadStatus.Connected, DownLoadStatus.Connecting, DownLoadStatus.Downloading
    63.                     Throw New InvalidOperationException("Destination Path cannot be changed while download is in progress")
    64.                 Case Else
    65.                     _destPath = Value
    66.             End Select
    67.         End Set
    68.     End Property
    69.     Public Property Referer() As String
    70.         Get
    71.             Return _referer
    72.         End Get
    73.         Set(ByVal Value As String)
    74.             Select Case _status
    75.                 Case DownLoadStatus.Connected, DownLoadStatus.Connecting, DownLoadStatus.Downloading
    76.                     Throw New InvalidOperationException("Referer cannot be changed while download is in progress")
    77.                 Case Else
    78.                     _referer = Value
    79.             End Select
    80.         End Set
    81.     End Property
    82.  
    83.     Public ReadOnly Property Status() As DownLoadStatus
    84.         Get
    85.             Return _status
    86.         End Get
    87.     End Property
    88.     Public ReadOnly Property Progress() As Double
    89.         Get
    90.             If _size = 0 Then
    91.                 Return 0
    92.             Else
    93.                 Return mRead / _size
    94.             End If
    95.         End Get
    96.     End Property
    97.     Public ReadOnly Property Size() As Long
    98.         Get
    99.             Return _size
    100.         End Get
    101.     End Property
    102.     Public ReadOnly Property Downloaded() As Long
    103.         Get
    104.             Return mRead
    105.         End Get
    106.     End Property
    107.     Public ReadOnly Property ErrorDescription() As String
    108.         Get
    109.             Return _errorDescription
    110.         End Get
    111.     End Property
    112.     Private Sub ChangeStatus(ByVal NewStatus As DownLoadStatus)
    113.         Dim Temp As DownLoadStatus
    114.         Temp = _status
    115.         _status = NewStatus
    116.         RaiseEvent StatusChanged(Me, Temp, NewStatus)
    117.     End Sub
    118.     Public Sub DownloadFile()
    119.         Dim bBuffer() As Byte
    120.         Const BlockSize As Integer = 4096
    121.         Dim iRead As Integer
    122.         Dim iReadTotal As Integer
    123.         Dim iTotalSize As Integer
    124.         If _sourceURL = "" Then
    125.             Throw New InvalidOperationException("No Source URL specified")
    126.             Exit Sub
    127.         End If
    128.         If _destPath = "" Then
    129.             Throw New InvalidOperationException("No Destination Path specified")
    130.             Exit Sub
    131.         End If
    132.  
    133.         Try
    134.             Call ChangeStatus(DownLoadStatus.Connecting)
    135.             Dim wr As HttpWebRequest = CType(WebRequest.Create(_sourceURL), HttpWebRequest)
    136.             If _referer <> "" Then
    137.                 wr.Referer = _referer
    138.             End If
    139.             Dim resp As HttpWebResponse = CType(wr.GetResponse(), HttpWebResponse)
    140.             _size = resp.ContentLength
    141.             Call ChangeStatus(DownLoadStatus.Connected)
    142.             Dim sIn As IO.Stream = resp.GetResponseStream
    143.             Dim sOut As New IO.FileStream(_destPath, IO.FileMode.Create)
    144.             ReDim bBuffer(BlockSize - 1)
    145.             Call ChangeStatus(DownLoadStatus.Downloading)
    146.             iRead = sIn.Read(bBuffer, 0, BlockSize)
    147.             mRead = iRead
    148.             While iRead > 0
    149.                 RaiseEvent ProgressChanged(Me)
    150.                 sOut.Write(bBuffer, 0, iRead)
    151.                 iRead = sIn.Read(bBuffer, 0, BlockSize)
    152.                 mRead += iRead
    153.             End While
    154.             sIn.Close()
    155.             sOut.Close()
    156.             Call ChangeStatus(DownLoadStatus.Completed)
    157.         Catch ex As Exception
    158.             _errorDescription = ex.Message
    159.             Call ChangeStatus(DownLoadStatus.ErrorOccured)
    160.         End Try
    161.     End Sub
    162.  
    163. End Class

  5. #5
    old fart Frans C's Avatar
    Join Date
    Oct 1999
    Location
    the Netherlands
    Posts
    2,926
    If I have more time, I will extend the error handling, and maybe add the possibility to resume broken downloads, but for now I think it's a good example for a download in a seperate thread.

    You can use the class like this.

    Add a button (Download), and a label (Label1) to a form.
    I omitted the form designer generated code.

    VB Code:
    1. Private WithEvents dlw As DownloadWorker
    2.  
    3.     Private Sub DownLoad_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles DownLoad.Click
    4.         dlw = New DownloadWorker("http://www.vbforums.com/images/toptitle-1.gif", "c:\temp\world.gif")
    5.  
    6.         Dim t As New Threading.Thread(AddressOf dlw.DownloadFile)
    7.         t.Start()
    8.     End Sub
    9.  
    10.     Private Sub dlw_ProgressChanged(ByRef sender As DownloadWorker) Handles dlw.ProgressChanged
    11.         Label1.Text = Format(sender.Progress, "0 %")
    12.     End Sub
    13.  
    14.     Private Sub dlw_StatusChanged(ByRef sender As DownloadWorker, ByVal OldStatus As DownloadClient.DownloadWorker.DownLoadStatus, ByVal NewStatus As DownloadClient.DownloadWorker.DownLoadStatus) Handles dlw.StatusChanged
    15.         Select Case NewStatus
    16.             Case DownloadWorker.DownLoadStatus.Completed
    17.                 Label1.Text = "Completed"
    18.             Case DownloadWorker.DownLoadStatus.Connected
    19.                 Label1.Text = "Connected"
    20.             Case DownloadWorker.DownLoadStatus.Connecting
    21.                 Label1.Text = "Connecting"
    22.             Case DownloadWorker.DownLoadStatus.Downloading
    23.                 Label1.Text = "Downloading"
    24.             Case DownloadWorker.DownLoadStatus.ErrorOccured
    25.                 Label1.Text = sender.ErrorDescription
    26.             Case DownloadWorker.DownLoadStatus.Idle
    27.                 Label1.Text = "Idle"
    28.         End Select
    29.     End Sub

  6. #6

    Thread Starter
    yay gay PT Exorcist's Avatar
    Join Date
    Apr 2002
    Location
    . . . my reason of shame
    Posts
    2,729
    ahh tks =)

  7. #7
    Member
    Join Date
    May 2002
    Location
    Malaysia
    Posts
    45
    Very nice Class.. but this one is work for HTTP download only right? do you have some idea on how to download file from FTP as well?

  8. #8

    Thread Starter
    yay gay PT Exorcist's Avatar
    Join Date
    Apr 2002
    Location
    . . . my reason of shame
    Posts
    2,729
    the size function doesnt return the size...as well as progress doesnt report the progress...the only function that still works is the downloaded() but it sometimes return the value in negative number...but thats not problem...

  9. #9
    old fart Frans C's Avatar
    Join Date
    Oct 1999
    Location
    the Netherlands
    Posts
    2,926
    I have noticed this as well when downloading from servers that don't return information about contentlength.
    If the size is unknown, the progress is unknown as well.

    Like I said, the error handling needs some work.

  10. #10

    Thread Starter
    yay gay PT Exorcist's Avatar
    Join Date
    Apr 2002
    Location
    . . . my reason of shame
    Posts
    2,729
    yea..that was the problem..he cannot save php and asp webpages :\

  11. #11

    Thread Starter
    yay gay PT Exorcist's Avatar
    Join Date
    Apr 2002
    Location
    . . . my reason of shame
    Posts
    2,729
    does anyone knows a way of workin around?

  12. #12

    Thread Starter
    yay gay PT Exorcist's Avatar
    Join Date
    Apr 2002
    Location
    . . . my reason of shame
    Posts
    2,729
    .


    ?

  13. #13

    Thread Starter
    yay gay PT Exorcist's Avatar
    Join Date
    Apr 2002
    Location
    . . . my reason of shame
    Posts
    2,729
    i noticed that when using this code the connection after the download is done never is closed...hmm..err

  14. #14
    Hyperactive Member stingrae's Avatar
    Join Date
    Apr 2002
    Location
    Sydney
    Posts
    401
    sweet! i like it a lot!

    just one additional question though (sorry )

    is there a way that you can view the web files properties too? by that i mean that i want to say to the user of my program "there is a new file for download that was created on the ..." and then give them the option to download it.

    in the code below i give them the details of a file they're about to overwrite. does anybody know of a way to view these properties for a file sitting on a web server?

    Code:
        Private Function DisplayFileDetails_Local()
            Dim fso As New FileSystemObject()
            Try
                txtLocalSize.Text = Format(fso.GetFile(txtFileName.Text).Size, "###,###,##0") & " bytes"
                txtLocalLastModified.Text = Format(fso.GetFile(txtFileName.Text).DateLastModified, "dd MMM yyyy")
                txtLocalLastAccessed.Text = Format(fso.GetFile(txtFileName.Text).DateLastAccessed, "dd MMM yyyy")
            Catch
                Debug.WriteLine(Err.Description)
            End Try
        End Function
    thanks.
    "The passion lives to keep your faith, though all are different, all are great" ... Michael Hutchence 1960-1997.

    Windows & Web Developer
    Specialising in Visual Basic .Net & Client Server Programming & Client/Customer Relations Databases
    Sutherland Shire, Sydney Australia
    www.stingrae.com.au
    Developer of Arnold - Gym & Martial Arts Database Management System
    www.gymdatabase.com.au

  15. #15
    Your Ad Here! Edneeis's Avatar
    Join Date
    Feb 2000
    Location
    Moreno Valley, CA (SoCal)
    Posts
    7,339
    If you wanted to use the Webclient still you can easily make it run asynchronously with a new thread or via a delegate and the begininvoke method. Although that doesn't provide a method of showing the progress. I think to get the progress you'd have to use OpenRead on the webclient to get the stream of the file. Then you can grab it in chunks and show progress that way.

    VB Code:
    1. Public Delegate Sub DoDownloadFile(ByVal url As String, ByVal file As String)
    2.  
    3.     Private Sub btnAsync_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnAsync.Click
    4.         Dim wc As New WebClient()
    5.         'make delegate from object method
    6.         Dim del As New DoDownloadFile(AddressOf wc.DownloadFile)
    7.         'start the download
    8.         del.BeginInvoke(txtURL.Text, txtLocal.Text, New AsyncCallback(AddressOf DownloadProgress), Nothing)
    9.         'if you don't care to check the completion or not then you can use to run it async still
    10.         'del.BeginInvoke(txtURL.Text, txtLocal.Text, Nothing, Nothing)
    11.     End Sub
    12.  
    13.     Private Sub DownloadProgress(ByVal ar As IAsyncResult)
    14.         'catch callbacks
    15.         If ar.IsCompleted Then
    16.             MsgBox("File Downloaded!")
    17.         Else
    18.             MsgBox("Download Failed!")
    19.         End If
    20.     End Sub

  16. #16
    Sleep mode
    Join Date
    Aug 2002
    Location
    RUH
    Posts
    8,083
    Originally posted by Frans C
    I have noticed this as well when downloading from servers that don't return information about contentlength.
    If the size is unknown, the progress is unknown as well.
    Like I said, the error handling needs some work.
    It's not any sort of problems ! even Windows default downloader (and sometimes Downloader Manager) returns no size nor the estimated time (it just shows ..#.downloaded so far . Your Class seems well-done and thanks for sharing it with us Frans C .

  17. #17
    Hyperactive Member stingrae's Avatar
    Join Date
    Apr 2002
    Location
    Sydney
    Posts
    401
    DownloadWorker is working fantastically! A big thanks to all of you on here.

    Don't suppose anyone has an UploadWorker too do they? That would be a big help!
    Last edited by stingrae; Jun 16th, 2003 at 12:35 AM.
    "The passion lives to keep your faith, though all are different, all are great" ... Michael Hutchence 1960-1997.

    Windows & Web Developer
    Specialising in Visual Basic .Net & Client Server Programming & Client/Customer Relations Databases
    Sutherland Shire, Sydney Australia
    www.stingrae.com.au
    Developer of Arnold - Gym & Martial Arts Database Management System
    www.gymdatabase.com.au

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  



Click Here to Expand Forum to Full Width