Вопрос по filesystemwatcher, ftp, c# – FileSystemWatcher для FTP

11

Как я могу реализоватьFileSystemWatcher для местоположения FTP (в C #). Идея заключается в том, что всякий раз, когда что-либо добавляется в расположение FTP, я хочу скопировать его на мой локальный компьютер. Любые идеи будут полезны.

Это продолжение моего предыдущего вопросаВыборочная загрузка по FTP с использованием .NET.

Вы собираетесь использовать подход типа опроса. Вы должны периодически проверять сайт ftp, чтобы проверить, существует ли новый файл. jersoft

Ваш Ответ

7   ответов
3

public class FtpFileSystemWatcher
{

    public bool IsRunning
    {
        get;
        private set;
    }
    public string FtpUserName
    {
        get;
        set;
    }
    public string FtpPassword
    {
        get;
        set;
    }
    public string FtpLocationToWatch
    {
        get;
        set;
    }
    public string DownloadTo
    {
        get;
        set;
    }
    public bool KeepOrignal
    {
        get;
        set;
    }
    public bool OverwriteExisting
    {
        get;
        set;
    }
    public int RecheckIntervalInSeconds
    {
        get;
        set;
    }
    private bool DownloadInprogress
    {
        get;
        set;
    }

    private System.Timers.Timer JobProcessor;

    public FtpFileSystemWatcher(string FtpLocationToWatch = "", string DownloadTo = "", int RecheckIntervalInSeconds = 1, string UserName = "", string Password = "", bool KeepOrignal = false, bool OverwriteExisting = false)
    {
        this.FtpUserName = UserName;
        this.FtpPassword = Password;
        this.FtpLocationToWatch = FtpLocationToWatch;
        this.DownloadTo = DownloadTo;
        this.KeepOrignal = KeepOrignal;
        this.RecheckIntervalInSeconds = RecheckIntervalInSeconds;
        this.OverwriteExisting = OverwriteExisting;

        if (this.RecheckIntervalInSeconds < 1) this.RecheckIntervalInSeconds = 1;
    }

    public void StartDownloading()
    {

        JobProcessor = new Timer(this.RecheckIntervalInSeconds * 1000);
        JobProcessor.AutoReset = false;
        JobProcessor.Enabled = false;
        JobProcessor.Elapsed += (sender, e) =>
        {
            try
            {

                this.IsRunning = true;

                string[] FilesList = GetFilesList(this.FtpLocationToWatch, this.FtpUserName, this.FtpPassword);

                if (FilesList == null || FilesList.Length < 1)
                {
                    return;
                }

                foreach (string FileName in FilesList)
                {
                    if (!string.IsNullOrWhiteSpace(FileName))
                    {
                        DownloadFile(this.FtpLocationToWatch, this.DownloadTo, FileName.Trim(), this.FtpUserName, this.FtpPassword, this.OverwriteExisting);

                        if (!this.KeepOrignal)
                        {
                            DeleteFile(Path.Combine(this.FtpLocationToWatch, FileName.Trim()), this.FtpUserName, this.FtpPassword);
                        }
                    }
                }

                this.IsRunning = false;
                JobProcessor.Enabled = true;                    
            }

            catch (Exception exp)
            {
                this.IsRunning = false;
                JobProcessor.Enabled = true;
                Console.WriteLin,e(exp.Message);
            }
        };

        JobProcessor.Start();
    }

    public void StopDownloading()
    {
        try
        {
            this.JobProcessor.Dispose();
            this.IsRunning = false;
        }
        catch { }
    }

    private void DeleteFile(string FtpFilePath, string UserName, string Password)
    {
        FtpWebRequest FtpRequest;
        FtpRequest = (FtpWebRequest)FtpWebRequest.Create(new Uri(FtpFilePath));
        FtpRequest.UseBinary = true;
        FtpRequest.Method = WebRequestMethods.Ftp.DeleteFile;

        FtpRequest.Credentials = new NetworkCredential(UserName, Password);
        FtpWebResponse response = (FtpWebResponse)FtpRequest.GetResponse();
        response.Close();

    }
    private void DownloadFile(string FtpLocation, string FileSystemLocation, string FileName, string UserName, string Password, bool OverwriteExisting)
    {
        try
        {
            const int BufferSize = 2048;
            byte[] Buffer = new byte[BufferSize];

            FtpWebRequest Request;
            FtpWebResponse Response;

            if (File.Exists(Path.Combine(FileSystemLocation, FileName)))
            {
                if (OverwriteExisting)
                {
                    File.Delete(Path.Combine(FileSystemLocation, FileName));
                }
                else
                {
                    Console.WriteLine(string.Format("File {0} already exist.", FileName));
                    return;
                }
            }

            Request = (FtpWebRequest)FtpWebRequest.Create(new Uri(Path.Combine(FtpLocation, FileName)));
            Request.Credentials = new NetworkCredential(UserName, Password);
            Request.Proxy = null;
            Request.Method = WebRequestMethods.Ftp.DownloadFile;
            Request.UseBinary = true;

            Response = (FtpWebResponse)Request.GetResponse();

            using (Stream s = Response.GetResponseStream())
            {
                using (FileStream fs = new FileStream(Path.Combine(FileSystemLocation, FileName), FileMode.Cr,eateNew, FileAccess.ReadWrite))
                {
                    while (s.Read(Buffer, 0, BufferSize) != -1)
                    {
                        fs.Write(Buffer, 0, BufferSize);
                    }
                }
            }
        }
        catch { }

    }
    private string[] GetFilesList(string FtpFolderPath, string UserName, string Password)
    {
        try
        {
            FtpWebRequest Request;
            FtpWebResponse Response;

            Request = (FtpWebRequest)FtpWebRequest.Create(new Uri(FtpFolderPath));
            Request.Credentials = new NetworkCredential(UserName, Password);
            Request.Proxy = null;
            Request.Method = WebRequestMethods.Ftp.ListDirectory;
            Request.UseBinary = true;

            Response = (FtpWebResponse)Request.GetResponse();
            StreamReader reader = new StreamReader(Response.GetResponseStream());
            string Data = reader.ReadToEnd();

            return Data.Split('\n');
        }
        catch
        {
            return null;
        }
    }


}
Пространства имен для будущих читателей: использование System; используя System.IO; используя System.Net; использование System.Timers;
15

при котором вы будете периодически запрашивать содержимое каталога. Сравните это с кэшированным списком из предыдущего вызова и определите, что произошло таким образом.

В протоколе FTP нет ничего, что могло бы помочь вам в этом, к сожалению.

0

загружая одноэлементный байтовый массив с именем & quot; .ftpComplete & quot ;. FileSystemWatcher отслеживает только «.ftpComplete» файлы, и удаляет это до конца, чтобы знать фактический загруженный файл. Поскольку ".ftpComplete" Файл занимает всего 1 байт, он загружается примерно так же быстро, как создается на FTP-сервере, поэтому его можно удалить, как только вы сделаете все, что вам нужно, с основным загруженным файлом.

        FtpWebRequest request = (FtpWebRequest)FtpWebRequest.Create(
            FTPAddress + "/" + Path.GetFileName(filePath) + ".ftpComplete");
        request.Method = WebRequestMethods.Ftp.UploadFile;
        request.Credentials = new NetworkCredential(username, password);
        request.UsePassive = true;
        request.UseBinary = true;
        request.KeepAlive = false;
        byte[] buffer = new byte[1];
        Stream reqStream = request.GetRequestStream();
        reqStream.Write(buffer, 0, buffer.Length);
        reqStream.Close();
0

айте FTP. Вот ссылка на пример сценария, который отправляет электронное письмо при обнаружении изменений:http://kb.robo-ftp.com/script_library/show/40

Я посмотрел на предыдущий вопрос, который вы связали. Я думаю, что вы сможете изменить образец Robo-FTP и использоватьSETLEFT введите команду / split, чтобы она проанализировала имя папки и номер файла ISO измененного файла, а затем переместите файл в нужное место.

7

FileSystemWatcher Класс работает, регистрируясь на события с операционной системой хоста Windows. Таким образом, он ограничен работой на локальных и UNC-путях к каталогам, размещенным в системах Windows. Документация MSDN поFileSystemWatcher объясняет пути, которые вы можете использовать, и некоторые потенциальные проблемы с использованием класса.

Если вы хотите получать уведомления об изменениях на FTP-сайте, вам нужно будет использовать механизм опроса, чтобы узнать текущее состояние файлов или папок, которые вы хотите отслеживать. Вы сможете увидеть, когда файлы добавляются и удаляются, сравнивая снимки FTP-сайта на предмет изменений и вызывая аналогичные события при обнаружении изменений. К сожалению, вы не сможете обнаружить события переименования, но другие изменения должны быть простыми для мониторинга таким образом.

3

указывающий на ваше местоположение ftp.

Затем, когда файл загружен или изменен, в вашем сервисе будет запущено событие, которое вы затем сможете использовать для копирования файла на локальный компьютер.
File.Copy и т. Д.

Посмотрел на:этот блог

Вы не можете использовать UNC-пути для ссылки на местоположения на FTP. UNC-пути подразумевают SMB / локальные Windows-пути.
Есть лиFileSystemWatcher работать с URL?
UNC-адреса, а не URL-адреса.
6

FileSystemWatcher или любым другим способом, потому что у протокола FTP нет API для уведомления клиента об изменениях в удаленном каталоге.

Все, что вы можете сделать, это периодически перебирать удаленное дерево и находить изменения.

Это на самом деле довольно легко реализовать, если вы используете клиентскую библиотеку FTP, которая поддерживает рекурсивный листинг удаленного дерева. К сожалению, встроенный .NET FTP-клиент,FtpWebRequest не. Но например сСборка WinSCP .NET версии 5.9 (или новее), вы можете использоватьSession.EnumerateRemoteFiles method.

Смотреть статьюНаблюдение за изменениями в SFTP / FTP-сервере:

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

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

    List<string> prevFiles = null;

    while (true)
    {
        // Collect file list
        List<string> files =
            session.EnumerateRemoteFiles(
                "/remote/path", "*.*", EnumerationOptions.AllDirectories)
            .Select(fileInfo => fileInfo.FullName)
            .ToList();
        if (prevFiles == null)
        {
            // In the first round, just print number of files found
            Console.WriteLine("Found {0} files", files.Count);
        }
        else
        {
            // Then look for differences against the previous list
            IEnumerable<string> added = files.Except(prevFiles);
            if (added.Any())
            {
                Console.WriteLine("Added files:");
                foreach (string path in added)
                {
                    Console.WriteLine(path);
                }
            }

            IEnumerable<string> removed = prevFiles.Except(files);
            if (removed.Any())
            {
                Console.WriteLine("Removed files:");
                foreach (string path in removed)
                {
                    Console.WriteLine(path);
                }
            }
        }

        prevFiles = files;

        Console.WriteLine("Sleeping 10s...");
        Thread.Sleep(10000);
    }
}

(I'm the author of WinSCP)

Хотя, если вы действительно хотите просто загрузить изменения, это намного проще. Просто используйтеSession.SynchronizeDirectories в петле.

session.SynchronizeDirectories(
    SynchronizationMode.Local, "/remote/path", @"C:\local\path", true).Check();

Если вы не хотите использовать стороннюю библиотеку, вы должны ограничитьсяFtpWebRequest, Например, как рекурсивно перечислить дерево удаленных каталогов с помощьюFtpWebRequestсмотри мой ответC # Скачать все файлы и подкаталоги через FTP.

Похожие вопросы