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 IEnumerable DirectoryListing()
{
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