FtpWebRequest Download File

152,739

Solution 1

This paragraph from the FptWebRequest class reference might be of interest to you:

The URI may be relative or absolute. If the URI is of the form "ftp://contoso.com/%2fpath" (%2f is an escaped '/'), then the URI is absolute, and the current directory is /path. If, however, the URI is of the form "ftp://contoso.com/path", first the .NET Framework logs into the FTP server (using the user name and password set by the Credentials property), then the current directory is set to /path.

Solution 2

I know this is an old Post but I am adding here for future reference. Here is a solution that I found:

    private void DownloadFileFTP()
    {
        string inputfilepath = @"C:\Temp\FileName.exe";
        string ftphost = "xxx.xx.x.xxx";
        string ftpfilepath = "/Updater/Dir1/FileName.exe";

        string ftpfullpath = "ftp://" + ftphost + ftpfilepath;

        using (WebClient request = new WebClient())
        {
            request.Credentials = new NetworkCredential("UserName", "P@55w0rd");
            byte[] fileData = request.DownloadData(ftpfullpath);

            using (FileStream file = File.Create(inputfilepath))
            {
                file.Write(fileData, 0, fileData.Length);
                file.Close();
            }
            MessageBox.Show("Download Complete");
        }
    }

Updated based upon excellent suggestion by Ilya Kogan

Solution 3

Easiest way

The most trivial way to download a binary file from an FTP server using .NET framework is using WebClient.DownloadFile:

WebClient client = new WebClient();
client.Credentials = new NetworkCredential("username", "password");
client.DownloadFile(
    "ftp://ftp.example.com/remote/path/file.zip", @"C:\local\path\file.zip");

Advanced options

Use FtpWebRequest, only if you need a greater control, that WebClient does not offer (like TLS/SSL encryption, progress monitoring, ascii/text transfer mode, resuming transfers, etc). Easy way is to just copy an FTP response stream to FileStream using Stream.CopyTo:

FtpWebRequest request =
    (FtpWebRequest)WebRequest.Create("ftp://ftp.example.com/remote/path/file.zip");
request.Credentials = new NetworkCredential("username", "password");
request.Method = WebRequestMethods.Ftp.DownloadFile;

using (Stream ftpStream = request.GetResponse().GetResponseStream())
using (Stream fileStream = File.Create(@"C:\local\path\file.zip"))
{
    ftpStream.CopyTo(fileStream);
}

Progress monitoring

If you need to monitor a download progress, you have to copy the contents by chunks yourself:

FtpWebRequest request =
    (FtpWebRequest)WebRequest.Create("ftp://ftp.example.com/remote/path/file.zip");
request.Credentials = new NetworkCredential("username", "password");
request.Method = WebRequestMethods.Ftp.DownloadFile;

using (Stream ftpStream = request.GetResponse().GetResponseStream())
using (Stream fileStream = File.Create(@"C:\local\path\file.zip"))
{
    byte[] buffer = new byte[10240];
    int read;
    while ((read = ftpStream.Read(buffer, 0, buffer.Length)) > 0)
    {
        fileStream.Write(buffer, 0, read);
        Console.WriteLine("Downloaded {0} bytes", fileStream.Position);
    }
}

For GUI progress (WinForms ProgressBar), see:
FtpWebRequest FTP download with ProgressBar


Downloading folder

If you want to download all files from a remote folder, see
C# Download all files and subdirectories through FTP.

Solution 4

I had the same issue!

My solution was to insert the public_html folder into the download URL.

Real file location on the server:

myhost.com/public_html/myimages/image.png

Web URL:

www.myhost.com/myimages/image.png

Solution 5

    private static DataTable ReadFTP_CSV()
    {
        String ftpserver = "ftp://servername/ImportData/xxxx.csv";
        FtpWebRequest reqFTP = (FtpWebRequest)FtpWebRequest.Create(new Uri(ftpserver));

        reqFTP.Credentials = new NetworkCredential(ftpUserID, ftpPassword);
        FtpWebResponse response = (FtpWebResponse)reqFTP.GetResponse();

        Stream responseStream = response.GetResponseStream();

        // use the stream to read file from FTP 
        StreamReader sr = new StreamReader(responseStream);
        DataTable dt_csvFile = new DataTable();

        #region Code
        //Add Code Here To Loop txt or CSV file
        #endregion

        return dt_csvFile;

    }

I hope it can help you.

Share:
152,739
Paul Michaels
Author by

Paul Michaels

I've been a programmer for most of my life. I have an interest in games, mobile and tablet development, along with message queuing, and pretty much anything that provides an elegant solution to a problem, technical or otherwise. I like learning new technology and finding new ways to use the old. I blog about my experiences here. You can read about me, or contact me on Linked in here.

Updated on July 09, 2022

Comments

  • Paul Michaels
    Paul Michaels almost 2 years

    The following code is intended to retrieve a file via FTP. However, I'm getting an error with it.

    serverPath = "ftp://x.x.x.x/tmp/myfile.txt";
    
    FtpWebRequest request = (FtpWebRequest)WebRequest.Create(serverPath);
    
    request.KeepAlive = true;
    request.UsePassive = true;
    request.UseBinary = true;
    
    request.Method = WebRequestMethods.Ftp.DownloadFile;                
    request.Credentials = new NetworkCredential(username, password);
    
    // Read the file from the server & write to destination                
    using (FtpWebResponse response = (FtpWebResponse)request.GetResponse()) // Error here
    using (Stream responseStream = response.GetResponseStream())
    using (StreamReader reader = new StreamReader(responseStream))            
    using (StreamWriter destination = new StreamWriter(destinationFile))
    {
        destination.Write(reader.ReadToEnd());
        destination.Flush();
    }
    

    The error is:

    The remote server returned an error: (550) File unavailable (e.g., file not found, no access)

    The file definitely does exist on the remote machine and I am able to perform this ftp manually (i.e. I have permissions). Can anyone tell me why I might be getting this error?

  • Ilya Kogan
    Ilya Kogan over 11 years
    Note that you should dispose of IDisposable objects. The easiest way to do this is to use the keyword using.
  • Mark Kram
    Mark Kram over 11 years
    You are correct, I posted this response when I was rather new to C#
  • Owen Blacker
    Owen Blacker over 11 years
    If you're going to use the WebClient, rather than the FtpWebRequest, you could use its DownloadFile method, rather than messing with a FileStream, which might be a little easier. There are some things that WebClient can't do, though (such as use ACTV rather than PASV FTP: FtpWebRequest.UsePassive = false;)
  • THE AMAZING
    THE AMAZING over 9 years
    proxy is nothing by default.
  • CularBytes
    CularBytes about 8 years
    Well, for me it was a matter of dealing with non-ASCII characters, like a # was in the URL, they have to be url encoded.
  • Donald.Record
    Donald.Record over 6 years
    How did you come up with the number "10240" for the buffer size?
  • Martin Prikryl
    Martin Prikryl over 6 years
    @Donald.Record It's a common practice for a file copy buffer to be in a magnitude of few KBs. It should be larger than a disk sector size. And I do not think that larger than 10KB helps anything. Though actually the Stream.CopyTo uses a buffer of 80 KB.