本文实例讲述了C#实现多线程下载文件的方法。分享给大家供大家参考。具体实现方法如下:
?| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191 | using System;using System.Collections.Generic;using System.Linq;using System.Text;using System.IO;using System.Threading;using System.Net;namespace WfpApp{public class MultiDownload{#region 变量private int _threadNum; //线程数量private long _fileSize; //文件大小private string _fileUrl; //文件地址private string _fileName; //文件名private string _savePath; //保存路径private short _threadCompleteNum; //线程完成数量private bool _isComplete; //是否完成private volatile int _downloadSize; //当前下载大小(实时的)private Thread[] _thread; //线程数组private List<string> _tempFiles = new List<string>();private object locker = new object();#endregion#region 属性/// <summary>/// 文件名/// </summary>public string FileName{get{return _fileName;}set{_fileName = value;}}/// <summary>/// 文件大小/// </summary>public long FileSize{get{return _fileSize;}}/// <summary>/// 当前下载大小(实时的)/// </summary>public int DownloadSize{get{return _downloadSize;}}/// <summary>/// 是否完成/// </summary>public bool IsComplete{get{return _isComplete;}}/// <summary>/// 线程数量/// </summary>public int ThreadNum{get{return _threadNum;}}/// <summary>/// 保存路径/// </summary>public string SavePath{get{return _savePath;}set{_savePath = value;}}#endregion/// <summary>/// 构造函数/// </summary>/// <param name="threahNum">线程数量</param>/// <param name="fileUrl">文件Url路径</param>/// <param name="savePath">本地保存路径</param>public MultiDownload(int threahNum, string fileUrl, string savePath){this._threadNum = threahNum;this._thread = new Thread[threahNum];this._fileUrl = fileUrl;this._savePath = savePath;}public void Start(){HttpWebRequest request = (HttpWebRequest)WebRequest.Create(_fileUrl);HttpWebResponse response = (HttpWebResponse)request.GetResponse();_fileSize = response.ContentLength;int singelNum = (int)(_fileSize / _threadNum); //平均分配int remainder = (int)(_fileSize % _threadNum); //获取剩余的request.Abort();response.Close();for (int i = 0; i < _threadNum; i++){List<int> range = new List<int>();range.Add(i * singelNum);if (remainder != 0 && (_threadNum - 1) == i) //剩余的交给最后一个线程range.Add(i * singelNum + singelNum + remainder - 1);elserange.Add(i * singelNum + singelNum - 1);//下载指定位置的数据int[] ran = new int[] { range[0], range[1] };_thread[i] = new Thread(new ParameterizedThreadStart(Download));_thread[i].Name = System.IO.Path.GetFileNameWithoutExtension(_fileUrl) + "_{0}".Replace("{0}", Convert.ToString(i + 1));_thread[i].Start(ran);}}private void Download(object obj){Stream httpFileStream = null, localFileStram = null;try{int[] ran = obj as int[];string tmpFileBlock = System.IO.Path.GetTempPath() + Thread.CurrentThread.Name + ".tmp";_tempFiles.Add(tmpFileBlock);HttpWebRequest httprequest = (HttpWebRequest)WebRequest.Create(_fileUrl);httprequest.AddRange(ran[0], ran[1]);HttpWebResponse httpresponse = (HttpWebResponse)httprequest.GetResponse();httpFileStream = httpresponse.GetResponseStream();localFileStram = new FileStream(tmpFileBlock, FileMode.Create);byte[] by = new byte[5000];int getByteSize = httpFileStream.Read(by, 0, (int)by.Length); //Read方法将返回读入by变量中的总字节数while (getByteSize > 0){Thread.Sleep(20);lock (locker) _downloadSize += getByteSize;localFileStram.Write(by, 0, getByteSize);getByteSize = httpFileStream.Read(by, 0, (int)by.Length);}lock (locker) _threadCompleteNum++;}catch (Exception ex){throw new Exception(ex.Message.ToString());}finally{if (httpFileStream != null) httpFileStream.Dispose();if (localFileStram != null) localFileStram.Dispose();}if (_threadCompleteNum == _threadNum){Complete();_isComplete = true;}}/// <summary>/// 下载完成后合并文件块/// </summary>private void Complete(){Stream mergeFile = new FileStream(@_savePath, FileMode.Create);BinaryWriter AddWriter = new BinaryWriter(mergeFile);foreach (string file in _tempFiles){using (FileStream fs = new FileStream(file, FileMode.Open)){BinaryReader TempReader = new BinaryReader(fs);AddWriter.Write(TempReader.ReadBytes((int)fs.Length));TempReader.Close();}File.Delete(file);}AddWriter.Close();}}} |
调用:
?| 12345 | string httpUrl = @"http://172.28.98.96/fdimsservice/2.rar";string saveUrl = System.Environment.GetFolderPath(Environment.SpecialFolder.Desktop) + "//" + System.IO.Path.GetFileName(httpUrl);int threadNumber = 5;MultiDownload md = new MultiDownload(threadNumber, httpUrl, saveUrl);md.Start(); |
希望本文所述对大家的C#程序设计有所帮助。








发表评论
◎欢迎参与讨论,请在这里发表您的看法、交流您的观点。