C#多线程断点续传的类

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


 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值