tags:

views:

696

answers:

5

How can I implement a FileSystemWatcher for an ftp location (in C#). The idea is whenever anything gets added in the ftp location I wish to copy it to my local machine. Any ideas will be helpful.

This is a follow up of my previous question.

+4  A: 

You're going to have to implement a polling solution, where you keep asking for the directory content periodically. Compare this to a cached list from the previous call and determine what happened that way.

There's nothing in the FTP protocol that will help you with this unfortunately.

Lasse V. Karlsen
+3  A: 

Write a simple service to create FileSystemWatcher, pointing at your ftp location.

Then when a file is uploaded or modified, an event will be fired in your service, which you can then use to copy the file to your local machine.
File.Copy etc.

Hav a look at: this blog

Bravax
Does `FileSystemWatcher` work with URLs?
John Saunders
UNC locations, not URL's.
Bravax
+3  A: 

The FileSystemWatcher class works by registering for events with the host Windows operating system. As such, it is limited to working on local paths and UNC paths to directories hosted on Windows systems. The MSDN documentation on FileSystemWatcher explains the paths which you can use and some of the potential problems with using the class.

If you are looking to be alerted to changes on an FTP site, you will have to use a polling mechanism to ask for the current status of files or folders you are interested in monitoring. You will be able to see when files are added and removed by comparing snapshots of the FTP site for changes and raising similar events when you detect changes. Unfortunately you wont be able to detect rename events, but other changes should be simple to monitor this way.

Programming Hero
+1  A: 

The way I handle this is to upload a one element byte array, named ".ftpComplete". The FileSystemWatcher only watches for ".ftpComplete" files, and strips that off the end to know the actual file uploaded. Since the".ftpComplete" file is only 1 byte, it uploads about as fast as it is created on the FTP server, so it can be deleted once you do whatever you need to with the main uploaded file

        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();
mikeh
A: 

You can monitor the FTP location by following method:

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.WriteLine(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.CreateNew, 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;
        }
    }


}
shafqat ali