PageRenderTime 26ms CodeModel.GetById 1ms app.highlight 18ms RepoModel.GetById 1ms app.codeStats 0ms

/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
 23using System;
 24using System.Collections.Generic;
 25using System.IO;
 26using System.Net;
 27
 28namespace CSFTPDownload
 29{
 30    public partial class FTPClientManager
 31    {
 32       
 33
 34        /// <summary>
 35        /// The Credentials to connect to the FTP server.
 36        /// </summary>
 37        public ICredentials Credentials { get; set; }
 38
 39        /// <summary>
 40        /// The current URL of this FTPClient.
 41        /// </summary>
 42        public Uri Url { get; private set; }
 43
 44        FTPClientManagerStatus status;
 45
 46        /// <summary>
 47        /// Get or Set the status of this FTPClient.
 48        /// </summary>
 49        public FTPClientManagerStatus Status
 50        {
 51            get
 52            {
 53                return status;
 54            }
 55
 56            private set
 57            {
 58                if (status != value)
 59                {
 60                    status = value;
 61
 62                    // Raise a OnStatusChanged event.
 63                    this.OnStatusChanged(EventArgs.Empty);
 64
 65                }
 66            }
 67        }
 68
 69        public event EventHandler UrlChanged;
 70
 71        public event EventHandler<ErrorEventArgs> ErrorOccurred;
 72
 73        public event EventHandler StatusChanged;
 74
 75        public event EventHandler<FileDownloadCompletedEventArgs> FileDownloadCompleted;
 76
 77        public event EventHandler<NewMessageEventArg> NewMessageArrived;
 78
 79        /// <summary>
 80        ///  Initialize a FTPClient instance.
 81        /// </summary>
 82        public FTPClientManager(Uri url, ICredentials credentials)
 83        {
 84            this.Credentials = credentials;
 85
 86            // Check whether the Url exists and the credentials is correct.
 87            // If there is an error, an exception will be thrown.
 88            CheckFTPUrlExist(url);
 89
 90            this.Url = url;
 91
 92            // Set the Status.
 93            this.Status = FTPClientManagerStatus.Idle;
 94
 95        }
 96
 97        /// <summary>
 98        /// Navigate to the parent folder.
 99        /// </summary>
100        public void NavigateParent()
101        {
102            if (Url.AbsolutePath != "/")
103            {
104
105                // Get the parent url.
106                Uri newUrl = new Uri(this.Url, "..");
107
108                // Check whether the Url exists.
109                CheckFTPUrlExist(newUrl);
110
111                this.Url = newUrl;
112                this.OnUrlChanged(EventArgs.Empty);
113            }
114        }
115
116        /// <summary>
117        /// Navigate a url.
118        /// </summary>
119        public void Naviagte(Uri newUrl)
120        {
121            // Check whether the Url exists.
122            bool urlExist = VerifyFTPUrlExist(newUrl);
123
124            this.Url = newUrl;
125            this.OnUrlChanged(EventArgs.Empty);
126        }
127
128        /// <summary>
129        /// If the Url does not exist, an exception will be thrown.
130        /// </summary>
131        void CheckFTPUrlExist(Uri url)
132        {
133            bool urlExist = VerifyFTPUrlExist(url);
134
135            if (!urlExist)
136            {
137                throw new ApplicationException("The url does not exist");
138            }
139        }
140
141        /// <summary>
142        /// Verify whether the url exists.
143        /// </summary>
144        bool VerifyFTPUrlExist(Uri url)
145        {
146            bool urlExist = false;
147
148            if (url.IsFile)
149            {
150                urlExist = VerifyFileExist(url);
151            }
152            else
153            {
154                urlExist = VerifyDirectoryExist(url);
155            }
156
157            return urlExist;
158        }
159
160        /// <summary>
161        /// Verify whether the directory exists.
162        /// </summary>
163        bool VerifyDirectoryExist(Uri url)
164        {
165            FtpWebRequest request = WebRequest.Create(url) as FtpWebRequest;
166            request.Credentials = this.Credentials;
167            request.Method = WebRequestMethods.Ftp.ListDirectory;
168
169            FtpWebResponse response = null;
170
171            try
172            {
173                response = request.GetResponse() as FtpWebResponse;
174
175                return response.StatusCode == FtpStatusCode.DataAlreadyOpen;
176            }
177            catch (System.Net.WebException webEx)
178            {
179                FtpWebResponse ftpResponse = webEx.Response as FtpWebResponse;
180
181                if (ftpResponse.StatusCode == FtpStatusCode.ActionNotTakenFileUnavailable)
182                {
183                    return false;
184                }
185
186                throw;
187            }
188            finally
189            {
190                if (response != null)
191                {
192                    response.Close();
193                }
194            }
195        }
196
197        /// <summary>
198        /// Verify whether the file exists.
199        /// </summary>
200        bool VerifyFileExist(Uri url)
201        {
202            FtpWebRequest request = WebRequest.Create(url) as FtpWebRequest;
203            request.Credentials = this.Credentials;
204            request.Method = WebRequestMethods.Ftp.GetFileSize;
205
206            FtpWebResponse response = null;
207
208            try
209            {
210                response = request.GetResponse() as FtpWebResponse;
211
212                return response.StatusCode == FtpStatusCode.FileStatus;
213            }
214            catch (System.Net.WebException webEx)
215            {
216                FtpWebResponse ftpResponse = webEx.Response as FtpWebResponse;
217
218                if (ftpResponse.StatusCode == FtpStatusCode.ActionNotTakenFileUnavailable)
219                {
220                    return false;
221                }
222
223                throw;
224            }
225            finally
226            {
227                if (response != null)
228                {
229                    response.Close();
230                }
231            }
232        }
233
234        /// <summary>
235        /// Get the sub directories and files of the current Url by dafault.
236        /// </summary>
237        public IEnumerable<FTPFileSystem> GetSubDirectoriesAndFiles()
238        {
239            return GetSubDirectoriesAndFiles(this.Url);
240        }
241
242        /// <summary>
243        /// Get the sub directories and files of the Url. It will be used in enumerate 
244        /// all the folders.
245        /// When run the FTP LIST protocol method to get a detailed listing of the files  
246        /// on an FTP server, the server will response many records of information. Each 
247        /// record represents a file. 
248        /// </summary>
249        public IEnumerable<FTPFileSystem> GetSubDirectoriesAndFiles(Uri url)
250        {
251            FtpWebRequest request = WebRequest.Create(url) as FtpWebRequest;
252
253            request.Credentials = this.Credentials;
254
255            request.Method = WebRequestMethods.Ftp.ListDirectoryDetails;
256
257
258            FtpWebResponse response = null;
259            Stream responseStream = null;
260            StreamReader reader = null;
261            try
262            {
263                response = request.GetResponse() as FtpWebResponse;
264
265                this.OnNewMessageArrived(new NewMessageEventArg
266                {
267                    NewMessage = response.StatusDescription
268                });
269
270                responseStream = response.GetResponseStream();
271                reader = new StreamReader(responseStream);
272
273                List<FTPFileSystem> subDirs = new List<FTPFileSystem>();
274
275                string subDir = reader.ReadLine();
276
277                // Find out the FTP Directory Listing Style from the recordString.
278                FTPDirectoryListingStyle style = FTPDirectoryListingStyle.MSDOS;
279                if (!string.IsNullOrEmpty(subDir))
280                {
281                    style = FTPFileSystem.GetDirectoryListingStyle(subDir);
282                }
283                while (!string.IsNullOrEmpty(subDir))
284                {
285                    subDirs.Add(FTPFileSystem.ParseRecordString(url, subDir, style));
286
287                    subDir = reader.ReadLine();
288                }
289                return subDirs;
290            }
291            finally
292            {
293                if (response != null)
294                {
295                    response.Close();
296                }
297
298                // Close the StreamReader object and the underlying stream, and release
299                // any system resources associated with the reader.
300                if (reader != null)
301                {
302                    reader.Close();
303                }
304            }
305        }
306
307        /// <summary>
308        /// Download files, directories and their subdirectories.
309        /// </summary>
310        public void DownloadDirectoriesAndFiles(IEnumerable<FTPFileSystem> files, string localPath)
311        {
312            if (this.status != FTPClientManagerStatus.Idle)
313            {
314                throw new ApplicationException("This client is busy now.");
315            }
316
317            this.Status = FTPClientManagerStatus.Downloading;
318
319            FTPDownloadClient downloadClient = new FTPDownloadClient(this);
320            downloadClient.FileDownloadCompleted += new EventHandler<FileDownloadCompletedEventArgs>(downloadClient_FileDownloadCompleted);
321            downloadClient.AllFilesDownloadCompleted += new EventHandler(downloadClient_AllFilesDownloadCompleted);
322            downloadClient.DownloadDirectoriesAndFiles(files,localPath);
323            
324        }
325
326        void downloadClient_AllFilesDownloadCompleted(object sender, EventArgs e)
327        {
328            this.Status = FTPClientManagerStatus.Idle;
329        }
330
331        void downloadClient_FileDownloadCompleted(object sender, FileDownloadCompletedEventArgs e)
332        {
333            this.OnFileDownloadCompleted(e);
334        }
335      
336        protected virtual void OnUrlChanged(EventArgs e)
337        {
338            if (UrlChanged != null)
339            {
340                UrlChanged(this, e);
341            }
342        }
343
344        protected virtual void OnStatusChanged(EventArgs e)
345        {
346            if (StatusChanged != null)
347            {
348                StatusChanged(this, e);
349            }
350        }
351
352        protected virtual void OnFileDownloadCompleted(FileDownloadCompletedEventArgs e)
353        {
354            if (FileDownloadCompleted != null)
355            {
356                FileDownloadCompleted(this, e);
357            }
358        }
359
360        protected virtual void OnErrorOccurred(ErrorEventArgs e)
361        {
362            this.Status = FTPClientManagerStatus.Idle;
363
364            if (ErrorOccurred != null)
365            {
366                ErrorOccurred(this, e);
367            }
368        }
369
370        protected virtual void OnNewMessageArrived(NewMessageEventArg e)
371        {
372            if (NewMessageArrived != null)
373            {
374                NewMessageArrived(this, e);
375            }
376        }
377    }
378}