PageRenderTime 47ms CodeModel.GetById 17ms RepoModel.GetById 0ms app.codeStats 1ms

/Visual Studio 2008/CSFTPDownload/FTPClientManager.cs

#
C# | 378 lines | 236 code | 68 blank | 74 comment | 34 complexity | 32aa348b064d2e74ef6b90f849104d74 MD5 | raw file
  1. /****************************** Module Header ******************************\
  2. * Module Name: FTPClientManager.cs
  3. * Project: CSFTPDownload
  4. * Copyright (c) Microsoft Corporation.
  5. *
  6. * The class FTPClientManager supplies following features:
  7. * 1. Verify whether a file or a directory exists on the FTP server.
  8. * 2. List subdirectories and files of a folder on the FTP server.
  9. * 3. Delete files or directories on the FTP server.
  10. * 4. Create a directory on the FTP server.
  11. * 5. Manage the FTPDownloadClient to download files from the FTP server.
  12. *
  13. *
  14. * This source is subject to the Microsoft Public License.
  15. * See http://www.microsoft.com/opensource/licenses.mspx#Ms-PL.
  16. * All other rights reserved.
  17. *
  18. * THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND,
  19. * EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED
  20. * WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR PURPOSE.
  21. \***************************************************************************/
  22. using System;
  23. using System.Collections.Generic;
  24. using System.IO;
  25. using System.Net;
  26. namespace CSFTPDownload
  27. {
  28. public partial class FTPClientManager
  29. {
  30. /// <summary>
  31. /// The Credentials to connect to the FTP server.
  32. /// </summary>
  33. public ICredentials Credentials { get; set; }
  34. /// <summary>
  35. /// The current URL of this FTPClient.
  36. /// </summary>
  37. public Uri Url { get; private set; }
  38. FTPClientManagerStatus status;
  39. /// <summary>
  40. /// Get or Set the status of this FTPClient.
  41. /// </summary>
  42. public FTPClientManagerStatus Status
  43. {
  44. get
  45. {
  46. return status;
  47. }
  48. private set
  49. {
  50. if (status != value)
  51. {
  52. status = value;
  53. // Raise a OnStatusChanged event.
  54. this.OnStatusChanged(EventArgs.Empty);
  55. }
  56. }
  57. }
  58. public event EventHandler UrlChanged;
  59. public event EventHandler<ErrorEventArgs> ErrorOccurred;
  60. public event EventHandler StatusChanged;
  61. public event EventHandler<FileDownloadCompletedEventArgs> FileDownloadCompleted;
  62. public event EventHandler<NewMessageEventArg> NewMessageArrived;
  63. /// <summary>
  64. /// Initialize a FTPClient instance.
  65. /// </summary>
  66. public FTPClientManager(Uri url, ICredentials credentials)
  67. {
  68. this.Credentials = credentials;
  69. // Check whether the Url exists and the credentials is correct.
  70. // If there is an error, an exception will be thrown.
  71. CheckFTPUrlExist(url);
  72. this.Url = url;
  73. // Set the Status.
  74. this.Status = FTPClientManagerStatus.Idle;
  75. }
  76. /// <summary>
  77. /// Navigate to the parent folder.
  78. /// </summary>
  79. public void NavigateParent()
  80. {
  81. if (Url.AbsolutePath != "/")
  82. {
  83. // Get the parent url.
  84. Uri newUrl = new Uri(this.Url, "..");
  85. // Check whether the Url exists.
  86. CheckFTPUrlExist(newUrl);
  87. this.Url = newUrl;
  88. this.OnUrlChanged(EventArgs.Empty);
  89. }
  90. }
  91. /// <summary>
  92. /// Navigate a url.
  93. /// </summary>
  94. public void Naviagte(Uri newUrl)
  95. {
  96. // Check whether the Url exists.
  97. bool urlExist = VerifyFTPUrlExist(newUrl);
  98. this.Url = newUrl;
  99. this.OnUrlChanged(EventArgs.Empty);
  100. }
  101. /// <summary>
  102. /// If the Url does not exist, an exception will be thrown.
  103. /// </summary>
  104. void CheckFTPUrlExist(Uri url)
  105. {
  106. bool urlExist = VerifyFTPUrlExist(url);
  107. if (!urlExist)
  108. {
  109. throw new ApplicationException("The url does not exist");
  110. }
  111. }
  112. /// <summary>
  113. /// Verify whether the url exists.
  114. /// </summary>
  115. bool VerifyFTPUrlExist(Uri url)
  116. {
  117. bool urlExist = false;
  118. if (url.IsFile)
  119. {
  120. urlExist = VerifyFileExist(url);
  121. }
  122. else
  123. {
  124. urlExist = VerifyDirectoryExist(url);
  125. }
  126. return urlExist;
  127. }
  128. /// <summary>
  129. /// Verify whether the directory exists.
  130. /// </summary>
  131. bool VerifyDirectoryExist(Uri url)
  132. {
  133. FtpWebRequest request = WebRequest.Create(url) as FtpWebRequest;
  134. request.Credentials = this.Credentials;
  135. request.Method = WebRequestMethods.Ftp.ListDirectory;
  136. FtpWebResponse response = null;
  137. try
  138. {
  139. response = request.GetResponse() as FtpWebResponse;
  140. return response.StatusCode == FtpStatusCode.DataAlreadyOpen;
  141. }
  142. catch (System.Net.WebException webEx)
  143. {
  144. FtpWebResponse ftpResponse = webEx.Response as FtpWebResponse;
  145. if (ftpResponse.StatusCode == FtpStatusCode.ActionNotTakenFileUnavailable)
  146. {
  147. return false;
  148. }
  149. throw;
  150. }
  151. finally
  152. {
  153. if (response != null)
  154. {
  155. response.Close();
  156. }
  157. }
  158. }
  159. /// <summary>
  160. /// Verify whether the file exists.
  161. /// </summary>
  162. bool VerifyFileExist(Uri url)
  163. {
  164. FtpWebRequest request = WebRequest.Create(url) as FtpWebRequest;
  165. request.Credentials = this.Credentials;
  166. request.Method = WebRequestMethods.Ftp.GetFileSize;
  167. FtpWebResponse response = null;
  168. try
  169. {
  170. response = request.GetResponse() as FtpWebResponse;
  171. return response.StatusCode == FtpStatusCode.FileStatus;
  172. }
  173. catch (System.Net.WebException webEx)
  174. {
  175. FtpWebResponse ftpResponse = webEx.Response as FtpWebResponse;
  176. if (ftpResponse.StatusCode == FtpStatusCode.ActionNotTakenFileUnavailable)
  177. {
  178. return false;
  179. }
  180. throw;
  181. }
  182. finally
  183. {
  184. if (response != null)
  185. {
  186. response.Close();
  187. }
  188. }
  189. }
  190. /// <summary>
  191. /// Get the sub directories and files of the current Url by dafault.
  192. /// </summary>
  193. public IEnumerable<FTPFileSystem> GetSubDirectoriesAndFiles()
  194. {
  195. return GetSubDirectoriesAndFiles(this.Url);
  196. }
  197. /// <summary>
  198. /// Get the sub directories and files of the Url. It will be used in enumerate
  199. /// all the folders.
  200. /// When run the FTP LIST protocol method to get a detailed listing of the files
  201. /// on an FTP server, the server will response many records of information. Each
  202. /// record represents a file.
  203. /// </summary>
  204. public IEnumerable<FTPFileSystem> GetSubDirectoriesAndFiles(Uri url)
  205. {
  206. FtpWebRequest request = WebRequest.Create(url) as FtpWebRequest;
  207. request.Credentials = this.Credentials;
  208. request.Method = WebRequestMethods.Ftp.ListDirectoryDetails;
  209. FtpWebResponse response = null;
  210. Stream responseStream = null;
  211. StreamReader reader = null;
  212. try
  213. {
  214. response = request.GetResponse() as FtpWebResponse;
  215. this.OnNewMessageArrived(new NewMessageEventArg
  216. {
  217. NewMessage = response.StatusDescription
  218. });
  219. responseStream = response.GetResponseStream();
  220. reader = new StreamReader(responseStream);
  221. List<FTPFileSystem> subDirs = new List<FTPFileSystem>();
  222. string subDir = reader.ReadLine();
  223. // Find out the FTP Directory Listing Style from the recordString.
  224. FTPDirectoryListingStyle style = FTPDirectoryListingStyle.MSDOS;
  225. if (!string.IsNullOrEmpty(subDir))
  226. {
  227. style = FTPFileSystem.GetDirectoryListingStyle(subDir);
  228. }
  229. while (!string.IsNullOrEmpty(subDir))
  230. {
  231. subDirs.Add(FTPFileSystem.ParseRecordString(url, subDir, style));
  232. subDir = reader.ReadLine();
  233. }
  234. return subDirs;
  235. }
  236. finally
  237. {
  238. if (response != null)
  239. {
  240. response.Close();
  241. }
  242. // Close the StreamReader object and the underlying stream, and release
  243. // any system resources associated with the reader.
  244. if (reader != null)
  245. {
  246. reader.Close();
  247. }
  248. }
  249. }
  250. /// <summary>
  251. /// Download files, directories and their subdirectories.
  252. /// </summary>
  253. public void DownloadDirectoriesAndFiles(IEnumerable<FTPFileSystem> files, string localPath)
  254. {
  255. if (this.status != FTPClientManagerStatus.Idle)
  256. {
  257. throw new ApplicationException("This client is busy now.");
  258. }
  259. this.Status = FTPClientManagerStatus.Downloading;
  260. FTPDownloadClient downloadClient = new FTPDownloadClient(this);
  261. downloadClient.FileDownloadCompleted += new EventHandler<FileDownloadCompletedEventArgs>(downloadClient_FileDownloadCompleted);
  262. downloadClient.AllFilesDownloadCompleted += new EventHandler(downloadClient_AllFilesDownloadCompleted);
  263. downloadClient.DownloadDirectoriesAndFiles(files,localPath);
  264. }
  265. void downloadClient_AllFilesDownloadCompleted(object sender, EventArgs e)
  266. {
  267. this.Status = FTPClientManagerStatus.Idle;
  268. }
  269. void downloadClient_FileDownloadCompleted(object sender, FileDownloadCompletedEventArgs e)
  270. {
  271. this.OnFileDownloadCompleted(e);
  272. }
  273. protected virtual void OnUrlChanged(EventArgs e)
  274. {
  275. if (UrlChanged != null)
  276. {
  277. UrlChanged(this, e);
  278. }
  279. }
  280. protected virtual void OnStatusChanged(EventArgs e)
  281. {
  282. if (StatusChanged != null)
  283. {
  284. StatusChanged(this, e);
  285. }
  286. }
  287. protected virtual void OnFileDownloadCompleted(FileDownloadCompletedEventArgs e)
  288. {
  289. if (FileDownloadCompleted != null)
  290. {
  291. FileDownloadCompleted(this, e);
  292. }
  293. }
  294. protected virtual void OnErrorOccurred(ErrorEventArgs e)
  295. {
  296. this.Status = FTPClientManagerStatus.Idle;
  297. if (ErrorOccurred != null)
  298. {
  299. ErrorOccurred(this, e);
  300. }
  301. }
  302. protected virtual void OnNewMessageArrived(NewMessageEventArg e)
  303. {
  304. if (NewMessageArrived != null)
  305. {
  306. NewMessageArrived(this, e);
  307. }
  308. }
  309. }
  310. }