0 votes

I have this working fine -

Using client As New Ftp()
    client.Connect("OnlineTarget")
    client.Login("Login", "Password")
    client.Download(TargetFile, MyFolder & "\" & TargetFile)
    client.Close()
End Using

However I need to monitor and show the progress of large file downloads. I have read the "Ftp Download and Upload Progress Event" blog item but I still need some advice to get my ProgressBar operating. I see it needs to be a separate thread, so please can you explain (in VB) what I need to do?

Thanks

by (750 points)

1 Answer

0 votes

If you want to track progress you need to subscribe to Progress event.

Take a look at this sample:

Imports System.Windows.Forms
Imports System.IO
Imports Limilabs.FTP.Client
Imports System.Threading

Public Class MainForm
    Inherits Form
    Private ReadOnly _btnUpload As Button
    Private ReadOnly _progressBar As ProgressBar
    Private ReadOnly _listBox As ListBox

    Public Sub New()
        _btnUpload = New Button()
        _btnUpload.Text = "Upload"
        AddHandler _btnUpload.Click, AddressOf btnUpload_Click
        _progressBar = New ProgressBar()
        _listBox = New ListBox()
        _btnUpload.Dock = DockStyle.Bottom
        _listBox.Dock = DockStyle.Fill
        _progressBar.Dock = DockStyle.Top
        Me.Controls.Add(_listBox)
        Me.Controls.Add(_progressBar)
        Me.Controls.Add(_btnUpload)
    End Sub

    Private Sub Ftp_Progress(ByVal sender As Object, ByVal e As
ProgressEventArgs)
        Me.BeginInvoke(Sub()
                           _progressBar.Value = CInt(e.Percentage)
                           _progressBar.Update()
                           _listBox.Items.Add(e.Percentage)
                       End Sub)
        Thread.Sleep(TimeSpan.FromSeconds(0.1))
    End Sub

    Private Sub btnUpload_Click(ByVal sender As Object, ByVal e As EventArgs)
        Dim thread As New Thread(AddressOf BackgroundThread)
        thread.Start()
    End Sub

    Private Sub BackgroundThread()

        Try
            Using ftp As New Ftp()
                AddHandler ftp.Progress, AddressOf Ftp_Progress
                ftp.Connect("localhost")
                Log("Connected. Logging in...")
                ftp.Login("ftptest", "cypher")
                Log("Logged in.")
                For Each fileName As String In Directory.GetFiles(".")
                    Log("Uploading: " + fileName)


                    ftp.Upload(Path.GetFileName(fileName), fileName)
                Next
                ftp.Close()
            End Using
        Catch ex As Exception
            Log(ex.ToString())
        End Try
    End Sub

    Private Sub Log(ByVal entry As String)
        Me.BeginInvoke(Function() _listBox.Items.Add(entry))
    End Sub

    <STAThread()> _
    Public Shared Sub Main()
        Application.EnableVisualStyles()
        Application.SetCompatibleTextRenderingDefault(False)
        Application.Run(New MainForm())
    End Sub
End Class
by (297k points)
Thank you, very helpful - I will get into this next.
NickB
Hello again,
Thanks for this - well understood. In one instance however I have to download a single large file (an occasional App update of 10MB+), and I want to display the percentage received with a 1-100 progress bar as the download progresses. The answer above works fine to monitor successive discrete file ops within a series, but how do I monitor and show the receipt progress of one large file as it is downloaded?
Ftp class has 2 events: Progress and BatchProgress. First is  to monitor progress on the single file, second to monitor where in the batch the process currently is.

The sample above is using Progress event - this is the one you are interested in.
Excellent, thank you - working fine.

One question: if the user wants to kill a large single-file up/download in mid-process your advice to someone was:

"You simply need to use Ftp.Abort method. It is thread safe. You can use it from any thread."

but once the ftp.Download(remote-address) operation is in progress - where would you put this Ftp.Abort instruction to intercept the working thread and safely stop that process? Sorry if this is a dumb question, but I can't see how to make it work.
Put in in the method that is invoked when user cancels the transfer.
But this will be outside the thread, where you can't refer to the ftp operation that is running in the thread -

    Private Sub BtnDownload_Click(ByVal sender As Object, ByVal e As EventArgs) _
    Handles _BtnDownload.Click
        Dim thread As New Thread(AddressOf BackgroundThread)
        thread.Start()
    End Sub

    Private Sub BackgroundThread()
        Try
            Using ftp As New Ftp()
                ftp.Connect("ftp-loc")
                ftp.Login("login", "password")
                ftp.Download(path-of-one-big-file)
                ftp.Close()
            End Using
        Catch ex As Exception
            
        End Try
    End Sub

    Private Sub Btn_Stop_Click(sender As System.Object, e As System.EventArgs) _
    Handles Btn_Stop.Click
        ' What goes here? Not Ftp.Abort() as this can't work ...
    End Sub

??
Please ask a separate question.
...