How to open an FTP connection and transfer a file [C#]

Shaitan00

Well-known member
Joined
Aug 11, 2003
Messages
343
Location
Hell
I need my C# code to be able to connect to an FTP (IP=10.10.10.1, USER=ADMIN, PASS=TOTAL) and download a file (Information.zip) stored in "\Stores\Details\" from the FTP Account HOME directory.
I need to save/copy the downloaded file to a specific location (C:\Temp\).

Problem - I have no clue how to open an FTP connection and perform an FTP file transfer in C#... currently I do everything directly (using \\MachineName\ and basic copy commands) but I am loosing that access and being forced to go through an FTP account.
Any help/hints would be greatly appreciated ... I hope this is a really simple/easy task...
Thanks,
 
Ftp is insanely simple.

Are you looking to use your own client..or go through the windows ftp app?

If you want to use the windows app, simply create a new process and send commands.

Heres a sample function...

Code:
        Dim myproc As New System.Diagnostics.Process

        You probably either want to make this an absolute path or set the directory
        myproc.StartInfo.FileName = "ftp"

        myproc.StartInfo.WindowStyle = ProcessWindowStyle.Hidden
        myproc.StartInfo.CreateNoWindow = True
        myproc.StartInfo.UseShellExecute = False
        myproc.StartInfo.RedirectStandardInput = True
         myproc.StartInfo.RedirectStandardOutput = True
         myproc.StartInfo.RedirectStandardError = True

         allow the process to raise events
        myproc.EnableRaisingEvents = True

         add an Exited event handler
        AddHandler myproc.Exited, AddressOf Me.ProcessExited

        Dim errorOutput As IO.StreamReader

        Try
            myproc.Start()
            ftpWriter = myproc.StandardInput
            ftpReader = myproc.StandardOutput()
             errorOutput = myproc.StandardError()
        Catch ex As Exception      You should catch a more specific exception
        End Try

        If Not (ftpWriter Is Nothing) Then
            Save starting time
      
        Send ftp commands
                ftpWriter.WriteLine("open " + obj.ToString())
                ftpWriter.WriteLine("O3a")
                ftpWriter.WriteLine("StRct")
                ftpWriter.WriteLine("bin")
                ftpWriter.WriteLine("prompt n")
                ftpWriter.WriteLine("lcd " + Me.outputDir)
                ftpWriter.WriteLine("cd s:")
                ftpWriter.WriteLine("mget *.dvr")
                ftpWriter.WriteLine("mdelete *.dvr")
                ftpWriter.WriteLine("Close")
                count = count + 1

                update progress bar every 10 seconds
                If updateTime.AddSeconds(10) < DateTime.Now Then
                    Me.UpdateData()
                    updateTime = DateTime.Now
                End If
            Next

            ftpWriter.Write("quit" + Chr(13))
        End If


Create a ftp client is also an option and is actually not that big of a project.

http://www.codeproject.com/csharp/ftpdriver1.asp
 
Sounds great but that is a new Process (thread)...
One thing I am wondering about, if my program launches this ftp process which needs to transfer a 100meg which should take around 2 minutes - I need to ensure my program waits for the FTP process to terminate.

Meaning, I cant have my program launch the ftp process/thread and then just simply move on because the next line of code is trying to open the file I just copied over via FTP...
 
Sure, thats what this line

Code:
   add an Exited event handler
        AddHandler myproc.Exited, AddressOf Me.ProcessExited

does.

It fires an event after the process has exited.

Handle the event any way you want...

Code:
  Private Sub ProcessExited(ByVal sender As Object, ByVal e As System.EventArgs)
        Dim myProcess As Process = CType(sender, Process)
        myProcess.Close()

        ftp finished, do something else
        End Sub



And I guess I should explain the other events.

This code:

Code:
                update progress bar every 10 seconds
                If updateTime.AddSeconds(10) < DateTime.Now Then
                     Me.UpdateData(startTime, totalFiles, filesCompleted)                    
                     updateTime = DateTime.Now
                End If

can be used to update the front end.

You could calculate the time remaining and then raise an event on the front end..as such:

Code:
    Private Sub UpdateData(ByVal startTime As DateTime, ByVal total As Integer, ByVal completed As Integer)
        take the elapsed time divided by completed records times total - completed
        Dim elapsed As TimeSpan = DateTime.Now.Subtract(startTime)
        Dim averageTime As Single = CType(elapsed.TotalSeconds, Single) / completed
        Dim timeLeft As Single = averageTime * (total - completed)
        Dim minutesLeft As Integer = CType(timeLeft / 60, Integer)
        Dim secondsLeft As Integer = CType(timeLeft Mod 60, Integer)

        If minutesLeft = 0 And secondsLeft = 0 Then
            lprogressText = "Calculating Time..."
        Else
            lprogressText = "Time Remaining: " + minutesLeft.ToString() + " minutes " + secondsLeft.ToString() + " seconds"
        End If

        RaiseEvent ProgressChanged(lprogressText, Nothing)
    End Sub

and you could handle the ProgressChanged event on the front end in a manner like so:

Code:
  Private Sub UpdateThreadData(ByVal sender As Object, ByVal e As EventArgs)

 Dim graphics As Drawing.Graphics = Me.CreateGraphics()
 graphics.FillRectangle(Drawing.SystemBrushes.Control, 32, 16, 250, 15)

        If NOT(sender Is Nothing) Then
            Update Progress Text 
            graphics.DrawString(sender.ToString(), New Drawing.Font(Drawing.FontFamily.GenericSerif, 10), Drawing.Brushes.Black, 32, 16)
        End If

    End Sub


One major problem with using a process is that its hard to handle errors. Or at least I havent found an easy way. If you had your own client, you could have a more robust error handling system.
 
Back
Top