打开APP
userphoto
未登录

开通VIP,畅享免费电子书等14项超值服

开通VIP
C#实现多线程下载文件的方法
[csharp] view plain copy
  1. using System;  
  2. using System.Collections.Generic;  
  3. using System.Linq;  
  4. using System.Text;  
  5. using System.IO;  
  6. using System.Threading;  
  7. using System.Net;  
  8. namespace WfpApp  
  9. {  
  10.  public class MultiDownload  
  11.  {  
  12.   #region 变量  
  13.   private int _threadNum;    //线程数量  
  14.   private long _fileSize;    //文件大小  
  15.   private string _fileUrl;   //文件地址  
  16.   private string _fileName;   //文件名  
  17.   private string _savePath;   //保存路径  
  18.   private short _threadCompleteNum; //线程完成数量  
  19.   private bool _isComplete;   //是否完成  
  20.   private volatile int _downloadSize; //当前下载大小(实时的)  
  21.   private Thread[] _thread;   //线程数组  
  22.   private List<string> _tempFiles = new List<string>();  
  23.   private object locker = new object();  
  24.   #endregion  
  25.   #region 属性  
  26.   /// <summary>  
  27.   /// 文件名  
  28.   /// </summary>  
  29.   public string FileName  
  30.   {  
  31.    get  
  32.    {  
  33.     return _fileName;  
  34.    }  
  35.    set  
  36.    {  
  37.     _fileName = value;  
  38.    }  
  39.   }  
  40.   /// <summary>  
  41.   /// 文件大小  
  42.   /// </summary>  
  43.   public long FileSize  
  44.   {  
  45.    get  
  46.    {  
  47.     return _fileSize;  
  48.    }  
  49.   }  
  50.   /// <summary>  
  51.   /// 当前下载大小(实时的)  
  52.   /// </summary>  
  53.   public int DownloadSize  
  54.   {  
  55.    get  
  56.    {  
  57.     return _downloadSize;  
  58.    }  
  59.   }  
  60.   /// <summary>  
  61.   /// 是否完成  
  62.   /// </summary>  
  63.   public bool IsComplete  
  64.   {  
  65.    get  
  66.    {  
  67.     return _isComplete;  
  68.    }  
  69.   }  
  70.   /// <summary>  
  71.   /// 线程数量  
  72.   /// </summary>  
  73.   public int ThreadNum  
  74.   {  
  75.    get  
  76.    {  
  77.     return _threadNum;  
  78.    }  
  79.   }  
  80.   /// <summary>  
  81.   /// 保存路径  
  82.   /// </summary>  
  83.   public string SavePath  
  84.   {  
  85.    get  
  86.    {  
  87.     return _savePath;  
  88.    }  
  89.    set  
  90.    {  
  91.     _savePath = value;  
  92.    }  
  93.   }  
  94.   #endregion  
  95.   /// <summary>  
  96.   /// 构造函数  
  97.   /// </summary>  
  98.   /// <param name="threahNum">线程数量</param>  
  99.   /// <param name="fileUrl">文件Url路径</param>  
  100.   /// <param name="savePath">本地保存路径</param>  
  101.   public MultiDownload(int threahNum, string fileUrl, string savePath)  
  102.   {  
  103.    this._threadNum = threahNum;  
  104.    this._thread = new Thread[threahNum];  
  105.    this._fileUrl = fileUrl;  
  106.    this._savePath = savePath;  
  107.   }  
  108.   public void Start()  
  109.   {  
  110.    HttpWebRequest request = (HttpWebRequest)WebRequest.Create(_fileUrl);  
  111.    HttpWebResponse response = (HttpWebResponse)request.GetResponse();  
  112.    _fileSize = response.ContentLength;  
  113.    int singelNum = (int)(_fileSize / _threadNum);  //平均分配  
  114.    int remainder = (int)(_fileSize % _threadNum);  //获取剩余的  
  115.    request.Abort();  
  116.    response.Close();  
  117.    for (int i = 0; i < _threadNum; i++)  
  118.    {  
  119.     List<int> range = new List<int>();  
  120.     range.Add(i * singelNum);  
  121.     if (remainder != 0 && (_threadNum - 1) == i) //剩余的交给最后一个线程  
  122.      range.Add(i * singelNum + singelNum + remainder - 1);  
  123.     else  
  124.      range.Add(i * singelNum + singelNum - 1);  
  125.     //下载指定位置的数据  
  126.     int[] ran = new int[] { range[0], range[1] };  
  127.     _thread[i] = new Thread(new ParameterizedThreadStart(Download));  
  128.     _thread[i].Name = System.IO.Path.GetFileNameWithoutExtension(_fileUrl) + "_{0}".Replace("{0}", Convert.ToString(i + 1));  
  129.     _thread[i].Start(ran);  
  130.    }  
  131.   }  
  132.   private void Download(object obj)  
  133.   {  
  134.    Stream httpFileStream = null, localFileStram = null;  
  135.    try  
  136.    {  
  137.     int[] ran = obj as int[];  
  138.     string tmpFileBlock = System.IO.Path.GetTempPath() + Thread.CurrentThread.Name + ".tmp";  
  139.     _tempFiles.Add(tmpFileBlock);  
  140.     HttpWebRequest httprequest = (HttpWebRequest)WebRequest.Create(_fileUrl);  
  141.     httprequest.AddRange(ran[0], ran[1]);  
  142.     HttpWebResponse httpresponse = (HttpWebResponse)httprequest.GetResponse();  
  143.     httpFileStream = httpresponse.GetResponseStream();  
  144.     localFileStram = new FileStream(tmpFileBlock, FileMode.Create);  
  145.     byte[] by = new byte[5000];  
  146.     int getByteSize = httpFileStream.Read(by, 0, (int)by.Length); //Read方法将返回读入by变量中的总字节数  
  147.     while (getByteSize > 0)  
  148.     {  
  149.      Thread.Sleep(20);  
  150.      lock (locker) _downloadSize += getByteSize;  
  151.      localFileStram.Write(by, 0, getByteSize);  
  152.      getByteSize = httpFileStream.Read(by, 0, (int)by.Length);  
  153.     }  
  154.     lock (locker) _threadCompleteNum++;  
  155.    }  
  156.    catch (Exception ex)  
  157.    {  
  158.     throw new Exception(ex.Message.ToString());  
  159.    }  
  160.    finally  
  161.    {  
  162.     if (httpFileStream != null) httpFileStream.Dispose();  
  163.     if (localFileStram != null) localFileStram.Dispose();  
  164.    }  
  165.    if (_threadCompleteNum == _threadNum)  
  166.    {  
  167.     Complete();  
  168.     _isComplete = true;  
  169.    }  
  170.   }  
  171.   /// <summary>  
  172.   /// 下载完成后合并文件块  
  173.   /// </summary>  
  174.   private void Complete()  
  175.   {  
  176.    Stream mergeFile = new FileStream(@_savePath, FileMode.Create);  
  177.    BinaryWriter AddWriter = new BinaryWriter(mergeFile);  
  178.    foreach (string file in _tempFiles)  
  179.    {  
  180.     using (FileStream fs = new FileStream(file, FileMode.Open))  
  181.     {  
  182.      BinaryReader TempReader = new BinaryReader(fs);  
  183.      AddWriter.Write(TempReader.ReadBytes((int)fs.Length));  
  184.      TempReader.Close();  
  185.     }  
  186.     File.Delete(file);  
  187.    }  
  188.    AddWriter.Close();  
  189.   }  
  190.  }  
  191. }  


调用方法:

[csharp] view plain copy
  1. string httpUrl = @"http://172.28.98.96/fdimsservice/2.rar";  
  2. string saveUrl = System.Environment.GetFolderPath(Environment.SpecialFolder.Desktop) + "//" + System.IO.Path.GetFileName(httpUrl);  
  3. int threadNumber = 5;  
  4. MultiDownload md = new MultiDownload(threadNumber, httpUrl, saveUrl);  
  5. md.Start();  





本站仅提供存储服务,所有内容均由用户发布,如发现有害或侵权内容,请点击举报
打开APP,阅读全文并永久保存 查看更多类似文章
猜你喜欢
类似文章
【热】打开小程序,算一算2024你的财运
多线程下载(FtpWebRequest)-程序开发-红黑联盟
图片与字符串的互相转换
在asp.net中使用jQuery实现类似QQ网站的图片切割效果
C# http下载(支持断点续传)
Winform中实现批量文件复制(附代码下载)
c# XML和实体类之间相互转换
更多类似文章 >>
生活服务
热点新闻
分享 收藏 导长图 关注 下载文章
绑定账号成功
后续可登录账号畅享VIP特权!
如果VIP功能使用有故障,
可点击这里联系客服!

联系客服