OdeToCode IC Logo

Building New Mouse Traps Part I: FTP

Saturday, November 26, 2005

I’m using the holiday break to build yet-another IIS log file retrieval / parser / reporting tool with Visual Studio 2005. Sure, there are plenty of these around already, but not that use Windows Workflow and SQL Server 2005 XML data types. If nothing else, the project was an exercise in learning new areas in 2005 and 2.0.

The first task was to retrieve a list of available log files from an FTP server. The 2.0 framework provides FTP support with the WebClient and FtpWebRequest classes. The WebClient is useful if you want a quick DownloadData call to retrieve an array of bytes. When dealing with large files you might not want the result in a single array, but instead stream bytes to a file as the download progresses.

I used the FtpWebRequest class, which like it’s cousin the WebRequest class, provides a heavily abstracted (yet amazingly low-level) interface for FTP work. If you are expecting to find a method to retrieve detailed file information, you won’t. You have to parse the directory list text yourself (see adarsh’s blog for a sample).

I went with the FtpWebRequest class to have control over streaming bytes to disk and parsing the directory contents.

public void DownloadFile(string remoteName, string localName)

{

    Check.IsRootedDirectoryName(localName, "localName");

    Check.IsNotNullOrEmpty(remoteName, "remoteName");

 

    WebRequest ftp = BuildFtpWebRequest(new Uri(remoteName));

    ftp.Method = WebRequestMethods.Ftp.DownloadFile;

 

    using (WebResponse response = ftp.GetResponse())

    using (BinaryReader reader = new BinaryReader(response.GetResponseStream()))

    using (BinaryWriter writer = new BinaryWriter(File.Open(localName, FileMode.Create)))

    {                                                             

        byte[] buffer = new byte[2048];

        int count = reader.Read(buffer, 0, buffer.Length);

        while (count != 0)

        {

            writer.Write(buffer, 0, count);

            count = reader.Read(buffer, 0, buffer.Length);

        }

    }

}

public List<string> GetFileNames(string remotePath)

{

    Check.IsNotNullOrEmpty(remotePath, "remotePath");

 

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

    WebRequest ftp = BuildFtpWebRequest(new Uri(remotePath));

    ftp.Method = WebRequestMethods.Ftp.ListDirectory;

 

    using (WebResponse response = ftp.GetResponse())

    using (StreamReader reader = new StreamReader(response.GetResponseStream()))

    {

        string line = reader.ReadLine();

        while (line != null)

        {

            result.Add(line);

            line = reader.ReadLine();

        }

    }

    return result;                       

}

 

 

protected virtual FtpWebRequest BuildFtpWebRequest(Uri uri)

{

    FtpWebRequest ftp = FtpWebRequest.Create(uri) as FtpWebRequest

        if (_credentials != null)

        {

            ftp.Credentials = _credentials;

        }           

    ftp.UseBinary = true;

 

    return ftp;

}