Рекурсивная загрузка на FTP-сервер в C# - PullRequest
0 голосов
/ 30 марта 2020

Мне нужно было бы загрузить папку (которая содержит подпапки и файлы) с одного сервера на другой из C# кода. Я провел небольшое исследование и обнаружил, что мы можем достичь этого с помощью FTP. Но при этом я могу перемещать только файлы, а не всю папку. Любая помощь здесь приветствуется.

1 Ответ

2 голосов
/ 30 марта 2020

FtpWebRequest (как и любой другой FTP-клиент в. NET framework) действительно не имеет явной поддержки рекурсивных файловых операций (включая загрузку). Вы должны реализовать рекурсию самостоятельно:

  • Перечислите локальный каталог
  • Итерируйте записи, загружая файлы и возвращаясь в подкаталоги (перечисляя их снова, et c.)
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);
    }
}

Сведения о сложном коде создания папок см. В
Как проверить, существует ли каталог FTP

Используйте такую ​​функцию, как:

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);

Более простой вариант, если вам не нужна рекурсивная загрузка:
Загрузка каталога файлов на FTP-сервер с использованием WebClient


Или используйте библиотеку FTP, которая может выполнять рекурсию самостоятельно.

Например, с WinSCP. NET сборка вы можете загрузить весь каталог с помощью одного вызова 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();
}

Метод Session.PutFilesToDirectory по умолчанию рекурсивный.

(я автор WinSCP)

...