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
}
}