Загрузка всех файлов с использованием FTP и C#

Каков наилучший способ загрузить все файлы в удаленный каталог с помощью С# и FTP и сохранить их в локальный каталог?

Спасибо.


person jumbojs    schedule 26.05.2009    source источник


Ответы (5)


загрузка всех файлов в определенную папку кажется простой задачей. Однако есть некоторые вопросы, которые необходимо решить. Назвать несколько:

Достойный сторонний FTP-компонент должен иметь метод решения этих проблем. Следующий код использует наш Rebex FTP для .NET.

using (Ftp client = new Ftp())
        {
            // connect and login to the FTP site
            client.Connect("mirror.aarnet.edu.au");
            client.Login("anonymous", "my@password");

            // download all files
            client.GetFiles(
                "/pub/fedora/linux/development/i386/os/EFI/*",
                "c:\\temp\\download",
                FtpBatchTransferOptions.Recursive,
                FtpActionOnExistingFiles.OverwriteAll
            );

            client.Disconnect();
        }

Код взят из моего сообщение в блоге доступно на сайте blog.rebex.net. В блоге также есть ссылка на пример, который показывает, как спросить пользователя, как справиться с каждой проблемой (например, перезаписать/перезаписать старые/пропустить/пропустить все).

person Martin Vobr    schedule 02.06.2009

Используя C# FtpWebRequest и FtpWebReponse, вы можете использовать следующую рекурсию (убедитесь, что строки папки заканчиваются на '\'):

    public void GetAllDirectoriesAndFiles(string getFolder, string putFolder)
    {
        List<string> dirIitems = DirectoryListing(getFolder);
        foreach (var item in dirIitems)
        {
            if ( item.Contains('.')  )
            {
                GetFile(getFolder + item, putFolder + item);
            }
            else
            {
                var subDirPut = new DirectoryInfo(putFolder + "\\" + item);
                subDirPut.Create();
                GetAllDirectoriesAndFiles(getFolder + item + "\\", subDirPut.FullName + "\\");
            }
        }
    }

"item.Contains('.')" немного примитивен, но для моих целей сработал. Оставьте комментарий, если вам нужен пример методов:

GetFile(string getFileAndPath, string putFileAndPath)

or

DirectoryListing(getFolder)
person Handprint    schedule 03.04.2012

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

  • Список удаленного каталога
  • Повторите записи, загрузив файлы и рекурсивно по подкаталогам (снова перечислив их и т. д.)

Сложная часть - идентифицировать файлы из подкаталогов. Невозможно сделать это переносимым способом с помощью FtpWebRequest. К сожалению, FtpWebRequest не поддерживает команду MLSD, которая является единственным переносимым способом получения списка каталогов с атрибутами файлов в протоколе FTP. См. также Проверка того, является ли объект на FTP-сервере файлом или каталогом.

Ваши варианты:

  • Выполните операцию над именем файла, которая наверняка завершится ошибкой для файла и будет успешной для каталогов (или наоборот). т.е. можно попробовать скачать "имя". Если это удается, это файл, если нет, это каталог. Но это может стать проблемой производительности, когда у вас большое количество записей.
  • Вам может повезти, и в вашем конкретном случае вы можете отличить файл от каталога по имени файла (т.е. все ваши файлы имеют расширение, а подкаталоги - нет)
  • Вы используете длинный список каталогов (команда LIST = метод ListDirectoryDetails) и пытаетесь проанализировать список для конкретного сервера. Многие FTP-серверы используют список в стиле *nix, где вы идентифицируете каталог по d в самом начале записи. Но многие серверы используют другой формат. В следующем примере используется этот подход (при условии, что формат * nix)
void DownloadFtpDirectory(string url, NetworkCredential credentials, string localPath)
{
    FtpWebRequest listRequest = (FtpWebRequest)WebRequest.Create(url);
    listRequest.UsePassive = true;
    listRequest.Method = WebRequestMethods.Ftp.ListDirectoryDetails;
    listRequest.Credentials = credentials;

    List<string> lines = new List<string>();

    using (WebResponse listResponse = listRequest.GetResponse())
    using (Stream listStream = listResponse.GetResponseStream())
    using (StreamReader listReader = new StreamReader(listStream))
    {
        while (!listReader.EndOfStream)
        {
            lines.Add(listReader.ReadLine());
        }
    }

    foreach (string line in lines)
    {
        string[] tokens =
            line.Split(new[] { ' ' }, 9, StringSplitOptions.RemoveEmptyEntries);
        string name = tokens[8];
        string permissions = tokens[0];

        string localFilePath = Path.Combine(localPath, name);
        string fileUrl = url + name;

        if (permissions[0] == 'd')
        {
            Directory.CreateDirectory(localFilePath);
            DownloadFtpDirectory(fileUrl + "/", credentials, localFilePath);
        }
        else
        {
            FtpWebRequest downloadRequest = (FtpWebRequest)WebRequest.Create(fileUrl);
            downloadRequest.UsePassive = true;
            downloadRequest.UseBinary = true;
            downloadRequest.Method = WebRequestMethods.Ftp.DownloadFile;
            downloadRequest.Credentials = credentials;

            using (Stream ftpStream = downloadRequest.GetResponse().GetResponseStream())
            using (Stream fileStream = File.Create(localFilePath))
            {
                ftpStream.CopyTo(fileStream);
            }
        }
    }
}

url должно быть таким:

  • ftp://example.com/ or
  • ftp://example.com/path/

Или используйте стороннюю библиотеку, поддерживающую рекурсивную загрузку.

Например, с помощью сборки WinSCP .NET вы можете загрузить весь каталог одним вызовом Session.GetFiles:

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

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

    // Download files
    session.GetFiles("/home/user/*", @"d:\download\").Check();
} 

Внутри WinSCP использует команду MLSD, если она поддерживается сервером. Если нет, он использует команду LIST и поддерживает десятки различных форматов листинга.

(я автор WinSCP)

person Martin Prikryl    schedule 19.05.2016
comment
Как раз собираюсь загрузить winSCP именно для этой цели, заранее спасибо. Почувствовал, что это может сэкономить мне время. - person ; 18.07.2017

Вы можете использовать System.Net.WebClient.DownloadFile(), который поддерживает FTP. Подробности MSDN здесь

person STW    schedule 08.10.2010

Вы можете использовать FTPClient от laedit.net. Он находится под лицензией Apache и прост в использовании.

Он использует FtpWebRequest :

  • сначала вам нужно использовать WebRequestMethods.Ftp.ListDirectoryDetails, чтобы получить подробную информацию обо всем списке папки
  • для каждого файла вам нужно использовать WebRequestMethods.Ftp.DownloadFile, чтобы загрузить его в локальную папку
person Jérémie Bertrand    schedule 19.09.2010