I had to put together an ftp client to test some application today - nothing much just needed the listing and upload features.
Below is what i came up with:
Ran into an issue setting the root directory and it took me a while to understand it. From MSDN:
Of course, it doesn't do much at the moment, I intend to add some more commands to it soon. I also want to try out an async upload option.
Below is what i came up with:
public class FtpClient { private const string FtpProtocolHeader = "ftp://"; private const string EscapedForwardSlash = "%2f"; private string requestUriString; public string RequestUriString { get { return requestUriString; } } private string UserName { get; set; } private SecureString Password { get; set; } private FtpClient() { } public FtpClient(string uri, string userId, string password) { requestUriString = BuildUri(uri); UserName = userId; char[] passwordChars = password.ToCharArray(); Password = new SecureString(); foreach (char c in passwordChars) Password.AppendChar(c); } private static string BuildUri(string uri) { if (!System.Uri.IsWellFormedUriString(uri, UriKind.Absolute)) throw new ArgumentException("Parameter is not well formed", "uri"); if (!uri.StartsWith(FtpProtocolHeader, StringComparison.OrdinalIgnoreCase)) uri = FtpProtocolHeader + uri; if (!uri.EndsWith("/", StringComparison.OrdinalIgnoreCase)) uri += "/"; return uri; } public FtpClient(string uri, string userId, SecureString password) { requestUriString = BuildUri(uri); UserName = userId; Password = password; } public IEnumerableDirectoryListing() { return DirectoryListing(null); } public IEnumerable DirectoryListing(string targetDir) { if (!string.IsNullOrWhiteSpace(targetDir)) { BuildRequestUri(targetDir); } try { FtpWebRequest request = (FtpWebRequest)WebRequest.Create(RequestUriString); request.Proxy = null; request.Method = WebRequestMethods.Ftp.ListDirectory; request.Credentials = new NetworkCredential(UserName, Password); using (FtpWebResponse response = (FtpWebResponse)request.GetResponse()) { using (Stream responseStream = response.GetResponseStream()) { if (responseStream == null) return null; List result; using (var reader = new StreamReader(responseStream)) { result = new List (); while (!reader.EndOfStream) { result.Add(reader.ReadLine()); } } return result; } } } catch (Exception) { throw; } } private void BuildRequestUri(string targetDir) { Debug.Assert(requestUriString != null, "requestUriString != null"); if (!String.IsNullOrWhiteSpace(targetDir) && targetDir.StartsWith("/")) { targetDir = targetDir.Substring(1); requestUriString += string.Format("{0}{1}", EscapedForwardSlash, targetDir); } } public bool UploadFile(string fileSourcePath, string targetDir) { if (!File.Exists(fileSourcePath)) { throw new ArgumentException("File path is invalid", "fileSourcePath"); } string fileName = Path.GetFileName(fileSourcePath); BuildRequestUri(targetDir); try { // Get the object used to communicate with the server. FtpWebRequest request = (FtpWebRequest)WebRequest.Create(RequestUriString + fileName); request.UseBinary = true; request.Proxy = null; request.Method = WebRequestMethods.Ftp.UploadFile; // use the credentials request.Credentials = new NetworkCredential(UserName, Password); byte[] fileContent = File.ReadAllBytes(fileSourcePath); request.ContentLength = fileContent.Length; using (Stream requestStream = request.GetRequestStream()) { requestStream.Write(fileContent, 0, fileContent.Length); } FtpWebResponse response = (FtpWebResponse)request.GetResponse(); return (response.StatusCode == FtpStatusCode.ClosingData); } catch { throw; } } }
The URI may be relative or absolute. If the URI is of the form "ftp://contoso.com/%2fpath" (%2f is an escaped '/'), then the URI is absolute, and the current directory is /path. If, however, the URI is of the form "ftp://contoso.com/path", first the .NET Framework logs into the FTP server (using the user name and password set by the Credentials property), then the current directory is set to /path.
Of course, it doesn't do much at the moment, I intend to add some more commands to it soon. I also want to try out an async upload option.
No comments:
Post a Comment