www.pudn.com > SharpDownload(FTP¼°WEBÏÂÔØ).zip > FileDownload.cs


using System; 
using System.Collections; 
using System.Diagnostics; 
using System.IO; 
using System.Threading; 
 
namespace SharpDownload 
{ 
	///  
	/// The File Download class controls and monitors progress of downloading a file. 
	///  
	public class FileDownload 
	{ 
		private string localFolder; 
		private DownloadInfo downloadInfo = new DownloadInfo(); 
		private FileDownloadModeEnum fileMode = FileDownloadModeEnum.BinaryMode; 
		 
		private ArrayList fileParts; 
 
		private bool deletePartsAfterCombine = false; 
 
		private FileDownloadCommandEnum downloadCommand = FileDownloadCommandEnum.NoCommand; 
		private const long MIN_SPLIT_SIZE = 20000; 
		private const int MAX_FILE_PARTS = 4; 
 
		#region ENUM 
		///  
		/// File download mode type 
		/// Used to indicate Binary or ASCII mode 
		///  
		public enum FileDownloadModeEnum 
		{ 
			///  
			/// Binary mode download 
			///  
			BinaryMode, 
			///  
			/// ASCII mode download 
			///  
			ASCIIMode 
		} 
		///  
		/// File download command 
		/// Use to send commands to an already running downloading 
		///  
		public enum FileDownloadCommandEnum 
		{ 
			///  
			/// No command (default) 
			///  
			NoCommand, 
			///  
			/// Pause the download 
			///  
			Pause, 
			///  
			/// Stop the download 
			///  
			Stop 
		} 
		#endregion 
		 
		///  
		/// Default constructor 
		///  
		public FileDownload() 
		{ 
		} 
 
		///  
		/// Creates a number of file parts 
		///  
		/// The number of file parts to create 
		public void CreateFileParts(int numParts) 
		{ 
			// Make sure valid number of parts 
			if (numParts<=0) 
			{ 
				throw new ApplicationException("Invalid number of file parts.  You must have at least one file part."); 
			} 
 
			// Create an array list and fill with FileParts 
			fileParts = new ArrayList(); 
			for (int i=0; i 
		/// Add a file part 
		///  
		public void AddFilePart() 
		{ 
			// Check if arraylist has been set up 
			if (fileParts==null) 
			{ 
				// Create a single file part 
				CreateFileParts(1); 
			} 
			else 
			{ 
				// Add a file part to the arraylist 
				fileParts.Add(new FilePart(fileParts.Count)); 
			} 
		} 
 
		///  
		/// Default indexer - returns a FilePart 
		///  
		public FilePart this [int index] 
		{ 
			get 
			{ 
				// Check that index is in bounds 
				if (index<0 || index>=fileParts.Count) 
				{ 
					throw new IndexOutOfRangeException(); 
				} 
				 
				return (FilePart)fileParts[index]; 
			} 
			set 
			{ 
				// Check that index is in bounds 
				if (index<0 || index>=fileParts.Count) 
				{ 
					throw new IndexOutOfRangeException(); 
				} 
				 
				fileParts[index] = value; 
				 
			} 
		} 
 
		///  
		/// Source address property.  Setting this property automatically 
		/// decomposes the URL into its component parts 
		///  
		public string SourceAddress 
		{ 
			get 
			{ 
				return downloadInfo.URL; 
			} 
			set 
			{ 
				downloadInfo.URL = value; 
			} 
		} 
 
		///  
		/// Destination folder to download the file to 
		///  
		public string LocalFolder 
		{ 
			get 
			{ 
				return localFolder; 
			} 
			set 
			{ 
				localFolder = value; 
				downloadInfo.LocalPath = value; 
			} 
		} 
		 
		///  
		/// Download mode for FTP downloads 
		///  
		public FileDownloadModeEnum FileDownloadMode 
		{ 
			get 
			{ 
				return fileMode; 
			} 
			set 
			{ 
				fileMode = value; 
			} 
		} 
 
		///  
		/// Number of bytes downloaded.  This is the sum of the file parts 
		///  
		public long BytesDownloaded 
		{ 
			get 
			{ 
				if (fileParts.Count==0) 
				{ 
					return 0; 
				} 
				else 
				{ 
					long amountDownloaded = 0; 
					// Count the amount downloaded 
					for (int i=0; i 
		/// Number of file parts in this file download 
		///  
		public int NumFileParts 
		{ 
			get 
			{ 
				return fileParts.Count; 
			} 
		} 
		 
		///  
		/// The download info component 
		///  
		public DownloadInfo DownloadInfo 
		{ 
			get 
			{ 
				return downloadInfo; 
			} 
		} 
 
		///  
		/// Public property to set/get the download command 
		///  
		public FileDownloadCommandEnum Command 
		{ 
			get 
			{ 
				return downloadCommand; 
			} 
			set 
			{ 
				downloadCommand = value; 
				if (fileParts==null) return; 
				foreach (FilePart part in fileParts) 
				{ 
					if (part != null) 
					{ 
						part.Command = value; 
					} 
				} 
			} 
		} 
 
		///  
		/// Asynchronous download call 
		///  
		/// true if download started successfully; false otherwise 
		public Thread AsyncDownload() 
		{ 
 
			try 
			{ 
				// Start a new thread 
				Thread downloadThread = new Thread(new ThreadStart(StartDownload)); 
				Debug.WriteLine("FileDownload: Download thread started"); 
				return downloadThread; 
			} 
			catch (Exception eThread) 
			{ 
				OnDownloadFailedEvent(new DownloadFailedEventArgs(eThread.Message)); 
				Debug.WriteLine("FileDownload: Download thread FAILED"); 
				return null; 
			} 
		} 
 
		///  
		/// Start download function 
		///  
		///  
		public void StartDownload() 
		{ 
 
			ProtocolClient protoClient = null; 
 
			try 
			{ 
				// Set up the download 
				protoClient = ProtocolClient.GetProtocolClient(downloadInfo); 
 
				// Check if logged in  
				if (!protoClient.IsLoggedIn) 
				{ 
					protoClient.Login(); 
				} 
 
				// Get the file size 
				try 
				{ 
					downloadInfo.FileSize = protoClient.GetFileSize(downloadInfo.Directory + "/" + downloadInfo.FileName); 
				} 
				catch (HttpClient.HttpRedirectException eRedirect) 
				{ 
					// Close the current client 
					protoClient.Close(); 
					// Change the download info to reflect the redirect 
					downloadInfo.URL = eRedirect.URL; 
					// Let's try the download again 
					this.StartDownload(); 
					return; 
				} 
			} 
			catch (ProtocolClient.ProtocolException e) 
			{ 
				// Exception occurred - exit for now 
				// TODO: Fix exception handling here! 
				OnDownloadFailedEvent(new DownloadFailedEventArgs(e.Message)); 
				return; 
			} 
 
			// Check if resume is supported 
			downloadInfo.ResumeSupported = protoClient.CanResume(downloadInfo.Directory + "/" + downloadInfo.FileName); 
			 
			// Close temporary protocol client 
			protoClient.Close(); 
			protoClient = null; 
 
			if (downloadInfo.ResumeSupported) 
			{ 
				// Split up the file 
				long totalFileSize = downloadInfo.FileSize; 
				long partLeftOver = 0; 
				long partFileSize = 0;	 
				if (totalFileSize>MIN_SPLIT_SIZE) 
				{ 
 
					// Calculate part sizes 
					partLeftOver = totalFileSize % MAX_FILE_PARTS; 
					partFileSize = (long)(totalFileSize - partLeftOver) / MAX_FILE_PARTS; 
 
					// Create the file parts 
					this.CreateFileParts(MAX_FILE_PARTS); 
					for (int i=0; i 
		/// Part Download Started event arguments 
		///  
		public class PartDownloadStartedEventArgs : EventArgs 
		{ 
			private readonly int partNumber; 
			private readonly long partSize; 
			///  
			/// PartDownloadStarted event arguments 
			///  
			/// The download part number that raised the event 
			/// The size of the part in Bytes 
			public PartDownloadStartedEventArgs (int PartNumber, long PartSize) 
			{ 
				partNumber = PartNumber; 
				partSize = PartSize; 
			} 
			///  
			/// Public read-only property for the part number 
			///  
			public int PartNumber 
			{ 
				get 
				{ 
					return partNumber; 
				} 
			} 
			///  
			/// Public read-only property for the size of the part in Bytes 
			///  
			public long PartSize 
			{ 
				get 
				{ 
					return partSize; 
				} 
			} 
		} 
		///  
		/// Delegate for Part Download Started Event 
		///  
		public delegate void PartDownloadStartedEventHandler(PartDownloadStartedEventArgs e); 
		///  
		/// The Part Download Started Event is raised when the part download starts 
		///  
		public event PartDownloadStartedEventHandler PartDownloadStartedEvent; 
		///  
		/// OnPartDownloadStartedEvent 
		///  
		/// PartDownloadStartedEventArgs 
		protected virtual void OnPartDownloadStartedEvent(PartDownloadStartedEventArgs e) 
		{ 
			if (PartDownloadStartedEvent != null) 
			{ 
				PartDownloadStartedEvent(e); 
			} 
		} 
 
		#endregion 
 
		#region DownloadStarted Event 
		///  
		/// Download started event arguments 
		///  
		public class DownloadStartedEventArgs : EventArgs 
		{ 
			private readonly long fileSize; 
			///  
			/// DownloadStarted event arguments 
			///  
			/// The size of the file in Bytes 
			public DownloadStartedEventArgs (long FileSize) 
			{ 
				fileSize = FileSize; 
			} 
			///  
			/// Public read-only property for the size of the file in Bytes 
			///  
			public long FileSize 
			{ 
				get 
				{ 
					return fileSize; 
				} 
			} 
		} 
		///  
		/// Delegate for Download Started Event 
		///  
		public delegate void DownloadStartedEventHandler(DownloadStartedEventArgs e); 
		///  
		/// The Download Started Event is raised when the download starts 
		///  
		public event DownloadStartedEventHandler DownloadStartedEvent; 
		///  
		/// OnDownloadStartedEvent 
		///  
		/// DownloadStartedEventArgs 
		protected virtual void OnDownloadStartedEvent(DownloadStartedEventArgs e) 
		{ 
			if (DownloadStartedEvent != null) 
			{ 
				DownloadStartedEvent(e); 
			} 
		} 
 
		#endregion 
 
		#region DataReceived Event 
		///  
		/// Data received event arguments 
		///  
		public class DataReceivedEventArgs : EventArgs 
		{ 
			private readonly int partNumber; 
			private readonly long bytesDownloaded; 
			///  
			/// DataReceived event arguments 
			///  
			/// The download part number that raised the event 
			/// The number of bytes downloaded 
			public DataReceivedEventArgs (int PartNumber, long BytesDownloaded) 
			{ 
				partNumber = PartNumber; 
				bytesDownloaded = BytesDownloaded; 
			} 
			///  
			/// Public read-only property  
			/// The download part number that raised the event 
			///  
			public int PartNumber 
			{ 
				get 
				{ 
					return partNumber; 
				} 
			} 
			///  
			/// Public read-only property 
			/// The number of Bytes downloaded 
			///  
			public long BytesDownloaded 
			{ 
				get 
				{ 
					return bytesDownloaded; 
				} 
			} 
		} 
		///  
		/// Delegate for Download Started Event 
		///  
		public delegate void DataReceivedEventHandler(DataReceivedEventArgs e); 
		///  
		/// The Download Started Event is raised when the download starts 
		///  
		public event DataReceivedEventHandler DataReceivedEvent; 
		///  
		/// OnDataReceivedEvent 
		///  
		/// DataReceivedEventArgs 
		protected virtual void OnDataReceivedEvent(DataReceivedEventArgs e) 
		{ 
			if (DataReceivedEvent != null) 
			{ 
				DataReceivedEvent(e); 
			} 
		} 
 
		#endregion 
 
		#region DownloadStopped Event 
		///  
		/// Download stopped event arguments 
		///  
		public class DownloadStoppedEventArgs : EventArgs 
		{ 
			private readonly int partNumber; 
			///  
			/// DownloadStopped event arguments 
			///  
			/// The part number that raised the event 
			/// The size of the file part in Bytes 
			public DownloadStoppedEventArgs (int PartNumber) 
			{ 
				partNumber = PartNumber; 
			} 
			///  
			/// Public read-only property 
			/// The download part number 
			///  
			public int PartNumber 
			{ 
				get 
				{ 
					return partNumber; 
				} 
			} 
		} 
		///  
		/// Delegate for Download Stopped Event 
		///  
		public delegate void DownloadStoppedEventHandler(DownloadStoppedEventArgs e); 
		///  
		/// The Download Sopped Event is raised when the download starts 
		///  
		public event DownloadStoppedEventHandler DownloadStoppedEvent; 
		///  
		/// OnDownloadStoppedEvent 
		///  
		/// DownloadStoppedEventArgs 
		protected virtual void OnDownloadStoppedEvent(DownloadStoppedEventArgs e) 
		{ 
			if (DownloadStoppedEvent != null) 
			{ 
				DownloadStoppedEvent(e); 
			} 
		} 
 
		#endregion 
 
		#region DownloadFinished Event 
		///  
		/// Download started event arguments 
		///  
		public class DownloadFinishedEventArgs : EventArgs 
		{ 
			private readonly int partNumber; 
			private readonly long partSize; 
			///  
			/// DownloadFinished event arguments 
			///  
			/// The part number that raised the event 
			/// The size of the file part in Bytes 
			public DownloadFinishedEventArgs (int PartNumber, long PartSize) 
			{ 
				partNumber = PartNumber; 
				partSize = PartSize; 
			} 
			///  
			/// Public read-only property 
			/// The download part number 
			///  
			public int PartNumber 
			{ 
				get 
				{ 
					return partNumber; 
				} 
			} 
			///  
			/// The size of the download part in Bytes 
			///  
			public long PartSize 
			{ 
				get 
				{ 
					return partSize; 
				} 
			} 
		} 
		///  
		/// Delegate for Download Started Event 
		///  
		public delegate void DownloadFinishedEventHandler(DownloadFinishedEventArgs e); 
		///  
		/// The Download Started Event is raised when the download starts 
		///  
		public event DownloadFinishedEventHandler DownloadFinishedEvent; 
		///  
		/// OnDownloadFinishedEvent 
		///  
		/// DownloadFinishedEventArgs 
		protected virtual void OnDownloadFinishedEvent(DownloadFinishedEventArgs e) 
		{ 
			if (DownloadFinishedEvent != null) 
			{ 
				DownloadFinishedEvent(e); 
			} 
		} 
 
		#endregion 
 
		#region DownloadCompleted Event 
		///  
		/// Download started event arguments 
		///  
		public class DownloadCompletedEventArgs : EventArgs 
		{ 
			///  
			/// Public default constructor 
			///  
			public DownloadCompletedEventArgs () 
			{ 
			} 
		} 
		///  
		/// Delegate for Download Started Event 
		///  
		public delegate void DownloadCompletedEventHandler(DownloadCompletedEventArgs e); 
		///  
		/// The Download Started Event is raised when the download starts 
		///  
		public event DownloadCompletedEventHandler DownloadCompletedEvent; 
		///  
		/// OnDownloadCompletedEvent 
		///  
		/// DownloadCompletedEventArgs 
		protected virtual void OnDownloadCompletedEvent(DownloadCompletedEventArgs e) 
		{ 
			if (DownloadCompletedEvent != null) 
			{ 
				DownloadCompletedEvent(e); 
			} 
		} 
 
		#endregion 
 
		#region DownloadFailed Event 
		///  
		/// Download failed event arguments 
		///  
		public class DownloadFailedEventArgs : EventArgs 
		{ 
			private string message = string.Empty; 
			///  
			/// DownloadFailed event arguments 
			///  
			/// The reason for the download failure (typically the error message raised) 
			public DownloadFailedEventArgs (string Message) 
			{ 
				message = Message; 
			} 
			///  
			/// Public read-only error message 
			///  
			public string Message 
			{ 
				get 
				{ 
					return message; 
				} 
			} 
		} 
		///  
		/// Delegate for Download Started Event 
		///  
		public delegate void DownloadFailedEventHandler(DownloadFailedEventArgs e); 
		///  
		/// The Download Started Event is raised when the download starts 
		///  
		public event DownloadFailedEventHandler DownloadFailedEvent; 
		///  
		/// OnDownloadFailedEvent 
		///  
		/// DownloadFailedEventArgs 
		protected virtual void OnDownloadFailedEvent(DownloadFailedEventArgs e) 
		{ 
			if (DownloadFailedEvent != null) 
			{ 
				DownloadFailedEvent(e); 
			} 
		} 
 
		#endregion 
 
	} 
}