Recursive upload to FTP server in C#
Asked Answered
C

1

2

I would need to upload a folder (which contains sub folders and files) from one server to another from C# code. I have done few research and found that we can achieve this using FTP. But with that I am able to move only files and not the entire folder. Any help here is appreciated.

Cariotta answered 30/3, 2020 at 6:27 Comment(0)
D
7

The FtpWebRequest (nor any other FTP client in .NET framework) indeed does not have any explicit support for recursive file operations (including uploads). You have to implement the recursion yourself:

  • List the local directory
  • Iterate the entries, uploading files and recursing into subdirectories (listing them again, etc.)
void UploadFtpDirectory(
  string sourcePath, string url, NetworkCredential credentials)
{
    IEnumerable<string> files = Directory.EnumerateFiles(sourcePath);
    foreach (string file in files)
    {
        using (WebClient client = new WebClient())
        {
            Console.WriteLine($"Uploading {file}");
            client.Credentials = credentials;
            client.UploadFile(url + Path.GetFileName(file), file);
        }
    }

    IEnumerable<string> directories = Directory.EnumerateDirectories(sourcePath);
    foreach (string directory in directories)
    {
        string name = Path.GetFileName(directory);
        string directoryUrl = url + name;

        try
        {
            Console.WriteLine($"Creating {name}");
            FtpWebRequest requestDir =
              (FtpWebRequest)WebRequest.Create(directoryUrl);
            requestDir.Method = WebRequestMethods.Ftp.MakeDirectory;
            requestDir.Credentials = credentials;
            requestDir.GetResponse().Close();
        }
        catch (WebException ex)
        {
            FtpWebResponse response = (FtpWebResponse)ex.Response;
            if (response.StatusCode ==
                  FtpStatusCode.ActionNotTakenFileUnavailable)
            {
                // probably exists already
            }
            else
            {
                throw;
            }
        }

        UploadFtpDirectory(directory, directoryUrl + "/", credentials);
    }
}

For the background of complicated code around creating the folders, see:
How to check if an FTP directory exists

Use the function like:

string sourcePath = @"C:\source\local\path";
// root path must exist
string url = "ftp://ftp.example.com/target/remote/path/";
NetworkCredential credentials = new NetworkCredential("username", "password");

UploadFtpDirectory(sourcePath, url, credentials);

A simpler variant, if you do not need a recursive upload:
Upload directory of files to FTP server using WebClient


Or use FTP library that can do the recursion on its own.

For example with WinSCP .NET assembly you can upload whole directory with a single call to the Session.PutFilesToDirectory:

// Setup session options
SessionOptions sessionOptions = new SessionOptions
{
    Protocol = Protocol.Ftp,
    HostName = "ftp.example.com",
    UserName = "username",
    Password = "password",
};

using (Session session = new Session())
{
    // Connect
    session.Open(sessionOptions);

    // Download files
    session.PutFilesToDirectory(
      @"C:\source\local\path", "/target/remote/path").Check();
}

The Session.PutFilesToDirectory method is recursive by default.

(I'm the author of WinSCP)

Dryden answered 30/3, 2020 at 7:25 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.