public class DownloadUtil
{
#region Fields
private static List<DownloadThread> downloadThreads;
#endregion
#region Sinleton instance
private static DownloadUtil instance;
/// <summary>
/// Singleton instance
/// </summary>
public static DownloadUtil Instance
{
get
{
if (instance == null)
{
instance = new DownloadUtil();
}
return instance;
}
}
#endregion
#region Events
/// <summary>
/// 当系统重新启动时,需要重新加载下载的线程列表时,给此Action赋值
/// </summary>
public Action<List<DownloadThread>> LoadDownloadThreadHandler;
#endregion
#region Private ctor
private DownloadUtil()
{
downloadThreads = new List<DownloadThread>();
// 根据外部业务逻辑初始化下载线程列表
if (LoadDownloadThreadHandler != null)
{
LoadDownloadThreadHandler(downloadThreads);
}
}
#endregion
#region Public methods
/// <summary>
/// Start download thread
/// </summary>
/// <param name="id"></param>
/// <param name="downloadUri"></param>
/// <param name="localFileFullPath"></param>
/// <param name="DownloadProgressChanged"></param>
/// <param name="DownloadCompleted"></param>
public void StartDownload(string id, string downloadUri, string localFileFullPath,
Action<double> DownloadProgressChanged,
Action DownloadCompleted)
{
DownloadThread downloadThread = new DownloadThread();
downloadThread.Id = id;
downloadThread.LocalFilePath = localFileFullPath;
downloadThread.DownloadUri = downloadUri;
Thread thread = new Thread(new ThreadStart(() =>
{
DownloadFileThread(localFileFullPath, downloadUri, DownloadProgressChanged, DownloadCompleted);
}));
downloadThread.Thread = thread;
downloadThread.DownloadProgressChanged = new Action<double>(DownloadProgressChanged);
downloadThread.DownloadCompleted = new Action(DownloadCompleted);
downloadThreads.Add(downloadThread);
downloadThread.Thread.Start();
}
/// <summary>
/// Pause download thread
/// </summary>
/// <param name="id"></param>
/// <returns>DownloadPosition</returns>
public void PauseDownload(string id, string localFileFullPath)
{
DownloadThread downloadThread = downloadThreads.FirstOrDefault(ele => ele.LocalFilePath == localFileFullPath
&& ele.Id == id);
if (downloadThread != null && downloadThread.Thread != null)
{
Thread thread = downloadThread.Thread;
thread.Abort();
}
}
/// <summary>
/// Resume download thread
/// </summary>
/// <param name="id"></param>
/// <param name="localFileFullPath"></param>
public void ResumeDownload(string id, string localFileFullPath)
{
DownloadThread downloadThread = downloadThreads.FirstOrDefault(ele => ele.LocalFilePath == localFileFullPath
&& ele.Id == id);
if (downloadThread != null && downloadThread.Thread != null)
{
Thread thread = new Thread(new ThreadStart(() =>
{
DownloadFileThread(localFileFullPath, downloadThread.DownloadUri,
downloadThread.DownloadProgressChanged,
downloadThread.DownloadCompleted);
}));
downloadThread.Thread = thread;
thread.Start();
}
}
/// <summary>
/// Delete download thread
/// </summary>
/// <param name="id"></param>
/// <param name="localFileFullPath"></param>
public void DeleteDownload(string id, string localFileFullPath)
{
DownloadThread downloadThread = downloadThreads.FirstOrDefault(ele => ele.LocalFilePath == localFileFullPath
&& ele.Id == id);
if (downloadThread != null)
{
if (downloadThread.Thread != null)
{
Thread thread = downloadThread.Thread;
thread.Abort();
}
downloadThreads.Remove(downloadThread);
}
}
#endregion
private void DownloadFileThread(string localFileFullPath, string downloadUri,
Action<double> downloadProgressChanged,
Action downloadCompleted)
{
FileInfo fi = new FileInfo(localFileFullPath);
FileStream fsToWrite;
if (!fi.Exists)
{
fsToWrite = fi.Create();
}
else
{
fsToWrite = fi.Open(FileMode.Append, FileAccess.Write, FileShare.Read);
}
long startPosition = fsToWrite.Length;
using (fsToWrite)
{
HttpWebRequest request = (HttpWebRequest)HttpWebRequest.Create(new Uri(downloadUri, UriKind.Absolute));
request.AddRange((int)startPosition);
try
{
HttpWebResponse response = (HttpWebResponse)request.GetResponse();
if (response != null)
{
Stream stream = response.GetResponseStream();
if (stream != null)
{
byte[] buffer = new byte[1024];
long contentTotalLength = response.ContentLength + startPosition;
int readLength = stream.Read(buffer, 0, buffer.Count());
long fileReadLength = startPosition + readLength;
double downloadPercent = Math.Round((double)fileReadLength * 100 / (double)contentTotalLength, 0);
double downloadPercentTemp = 0d;
while (readLength > 0)
{
fsToWrite.Write(buffer, 0, readLength);
readLength = stream.Read(buffer, 0, buffer.Count());
fileReadLength += readLength;
downloadPercentTemp = Math.Round((double)fileReadLength * 100 / (double)contentTotalLength, 0);
if (downloadProgressChanged != null && downloadPercent != downloadPercentTemp)
{
downloadPercent = downloadPercentTemp;
downloadProgressChanged.Invoke(downloadPercent);
}
}
DownloadThread downloadThread = downloadThreads.FirstOrDefault(ele => ele.LocalFilePath == localFileFullPath
&& ele.DownloadUri == downloadUri);
if (downloadThread != null)
{
downloadThreads.Remove(downloadThread);
}
if (downloadCompleted != null)
{
downloadCompleted.Invoke();
}
fsToWrite.Flush();
fsToWrite.Close();
}
}
}
catch (Exception)
{
}
}
}
}
在以上代码中用到的实体类
public class DownloadThread
{
private Thread downloadThread;
public Thread Thread
{
get { return downloadThread; }
set { downloadThread = value; }
}
private string id;
/// <summary>
/// 此处保存的是唯一标识
/// </summary>
public string Id
{
get { return id; }
set { id = value; }
}
private string localFilePath;
public string LocalFilePath
{
get { return localFilePath; }
set { localFilePath = value; }
}
private Action<double> downloadProgressChanged;
public Action<double> DownloadProgressChanged
{
get { return downloadProgressChanged; }
set { downloadProgressChanged = value; }
}
private Action downloadCompleted;
public Action DownloadCompleted
{
get { return downloadCompleted; }
set { downloadCompleted = value; }
}
private string downloadUri = string.Empty;
public string DownloadUri
{
get { return downloadUri; }
set { downloadUri = value; }
}
}