欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

C#限速下载网络文件的方法实例

程序员文章站 2022-04-01 09:10:34
c#限速下载网络文件的方法,具体如下: using system; using system.collections.concurrent; using...

c#限速下载网络文件的方法,具体如下:

using system;
using system.collections.concurrent;
using system.collections.generic;
using system.componentmodel;
using system.data;
using system.drawing;
using system.io;
using system.linq;
using system.net;
using system.text;
using system.text.regularexpressions;
using system.threading;
using system.threading.tasks;
using system.windows.forms;
using common.utils;
using utils;

namespace 爬虫
{
  public partial class form1 : form
  {
    #region 变量
    /// <summary>
    /// 已完成字节数
    /// </summary>
    private long completedcount = 0;
    /// <summary>
    /// 是否完成
    /// </summary>
    private bool iscompleted = true;
    /// <summary>
    /// 数据块队列
    /// </summary>
    private concurrentqueue<memorystream> msqueue = new concurrentqueue<memorystream>();
    /// <summary>
    /// 下载开始位置
    /// </summary>
    private long range = 0;
    /// <summary>
    /// 文件大小
    /// </summary>
    private long total = 0;
    /// <summary>
    /// 一段时间内的完成节点数,计算网速用
    /// </summary>
    private long unitcount = 0;
    /// <summary>
    /// 上次计时时间,计算网速用
    /// </summary>
    private datetime lasttime = datetime.minvalue;
    /// <summary>
    /// 一段时间内的完成字节数,控制网速用
    /// </summary>
    private long unitcountforlimit = 0;
    /// <summary>
    /// 上次计时时间,控制网速用
    /// </summary>
    private datetime lasttimeforlimit = datetime.minvalue;
    /// <summary>
    /// 下载文件sleep时间,控制速度用
    /// </summary>
    private int sleeptime = 1;
    #endregion

    #region form1
    public form1()
    {
      initializecomponent();
    }
    #endregion

    #region form1_load
    private void form1_load(object sender, eventargs e)
    {
      lblmsg.text = string.empty;
      lblbytemsg.text = string.empty;
      lblspeed.text = string.empty;
    }
    #endregion

    #region form1_formclosing
    private void form1_formclosing(object sender, formclosingeventargs e)
    {

    }
    #endregion

    #region btndownload_click 下载
    private void btndownload_click(object sender, eventargs e)
    {
      iscompleted = false;
      btndownload.enabled = false;
      string url = txturl.text.trim();
      string filepath = createfilepath(url);

      #region 下载线程
      thread thread = new thread(new threadstart(() =>
      {
        int trytimes = 0;
        while (!httpdownloadfile(url, filepath))
        {
          thread.sleep(10000);

          trytimes++;
          logutil.log("请求服务器失败,重新请求" + trytimes.tostring() + "次");
          this.invoke(new invokedelegate(() =>
          {
            lblmsg.text = "请求服务器失败,重新请求" + trytimes.tostring() + "次";
          }));
          httpdownloadfile(url, filepath);
        }
      }));
      thread.isbackground = true;
      thread.start();
      #endregion

      #region 保存文件线程
      thread = new thread(new threadstart(() =>
      {
        while (!iscompleted)
        {
          memorystream ms;
          if (msqueue.trydequeue(out ms))
          {
            using (filestream fs = new filestream(filepath, filemode.open, fileaccess.write))
            {
              fs.seek(completedcount, seekorigin.begin);
              fs.write(ms.toarray(), 0, (int)ms.length);
              fs.close();
            }
            completedcount += ms.length;
          }

          if (total != 0 && total == completedcount)
          {
            thread.sleep(100);
            iscompleted = true;
          }

          thread.sleep(1);
        }
      }));
      thread.isbackground = true;
      thread.start();
      #endregion

      #region 计算网速/进度线程
      thread = new thread(new threadstart(() =>
      {
        while (!iscompleted)
        {
          thread.sleep(1000);

          if (lasttime != datetime.minvalue)
          {
            double sec = datetime.now.subtract(lasttime).totalseconds;
            double speed = unitcount / sec / 1024;

            try
            {
              #region 显示速度
              if (speed < 1024)
              {
                this.invoke(new invokedelegate(() =>
                {
                  lblspeed.text = string.format("{0}kb/s", speed.tostring("0.00"));
                }));
              }
              else
              {
                this.invoke(new invokedelegate(() =>
                {
                  lblspeed.text = string.format("{0}mb/s", (speed / 1024).tostring("0.00"));
                }));
              }
              #endregion

              #region 显示进度
              this.invoke(new invokedelegate(() =>
              {
                string strtotal = (total / 1024 / 1024).tostring("0.00") + "mb";
                if (total < 1024 * 1024)
                {
                  strtotal = (total / 1024).tostring("0.00") + "kb";
                }
                string completed = (completedcount / 1024 / 1024).tostring("0.00") + "mb";
                if (completedcount < 1024 * 1024)
                {
                  completed = (completedcount / 1024).tostring("0.00") + "kb";
                }
                lblmsg.text = string.format("进度:{0}/{1}", completed, strtotal);
                lblbytemsg.text = string.format("已下载:{0}\r\n总大小:{1}", completedcount, total);

                if (completedcount == total)
                {
                  messagebox.show("完成");
                }
              }));
              #endregion
            }
            catch { }

            lasttime = datetime.now;
            unitcount = 0;
          }
        }
      }));
      thread.isbackground = true;
      thread.start();
      #endregion

      #region 限制网速线程
      thread = new thread(new threadstart(() =>
      {
        while (!iscompleted)
        {
          thread.sleep(100);

          if (lasttimeforlimit != datetime.minvalue)
          {
            double sec = datetime.now.subtract(lasttimeforlimit).totalseconds;
            double speed = unitcountforlimit / sec / 1024;

            try
            {
              #region 限速/解除限速
              double limitspeed = 0;
              if (double.tryparse(txtspeed.text.trim(), out limitspeed))
              {
                if (speed > limitspeed && sleeptime < 1000)
                {
                  sleeptime += 1;
                }
                if (speed < limitspeed - 10 && sleeptime >= 2)
                {
                  sleeptime -= 1;
                }
              }
              else
              {
                this.invoke(new invokedelegate(() =>
                {
                  txtspeed.text = "100";
                }));
              }
              #endregion
            }
            catch { }

            lasttimeforlimit = datetime.now;
            unitcountforlimit = 0;
          }
        }
      }));
      thread.isbackground = true;
      thread.start();
      #endregion

    }
    #endregion

    #region httpdownloadfile 下载文件
    /// <summary>
    /// http下载文件
    /// </summary>
    public bool httpdownloadfile(string url, string filepath)
    {
      try
      {
        if (!file.exists(filepath))
        {
          using (filestream fs = new filestream(filepath, filemode.create))
          {
            fs.close();
          }
        }
        else
        {
          fileinfo fileinfo = new fileinfo(filepath);
          range = fileinfo.length;
        }

        // 设置参数
        httpwebrequest request = webrequest.create(url) as httpwebrequest;
        request.useragent = "mozilla/4.0 (compatible; msie 8.0; windows nt 6.0; trident/4.0)";
        request.proxy = null;
        //发送请求并获取相应回应数据
        httpwebresponse response = request.getresponse() as httpwebresponse;
        if (response.contentlength == range)
        {
          this.invoke(new invokedelegate(() =>
          {
            lblmsg.text = "文件已下载";
          }));
          return true;
        }

        // 设置参数
        request = webrequest.create(url) as httpwebrequest;
        request.useragent = "mozilla/4.0 (compatible; msie 8.0; windows nt 6.0; trident/4.0)";
        request.proxy = null;
        request.addrange(range);
        //发送请求并获取相应回应数据
        response = request.getresponse() as httpwebresponse;
        //直到request.getresponse()程序才开始向目标网页发送post请求
        stream responsestream = response.getresponsestream();

        total = range + response.contentlength;
        completedcount = range;

        memorystream ms = new memorystream();
        byte[] barr = new byte[1024];
        lasttime = datetime.now;
        lasttimeforlimit = datetime.now;
        int size = responsestream.read(barr, 0, (int)barr.length);
        unitcount += size;
        unitcountforlimit += size;
        ms.write(barr, 0, size);
        while (!iscompleted)
        {
          size = responsestream.read(barr, 0, (int)barr.length);
          unitcount += size;
          unitcountforlimit += size;
          ms.write(barr, 0, size);
          if (ms.length > 102400)
          {
            msqueue.enqueue(ms);
            ms = new memorystream();
          }
          if (completedcount + ms.length == total)
          {
            msqueue.enqueue(ms);
            ms = new memorystream();
          }

          thread.sleep(sleeptime);
        }
        responsestream.close();
        return true;
      }
      catch (exception ex)
      {
        logutil.logerror(ex.message + "\r\n" + ex.stacktrace);
        return false;
      }
    }
    #endregion

    #region 根据url生成文件保存路径
    private string createfilepath(string url)
    {
      string path = application.startuppath + "\\download";
      if (!directory.exists(path))
      {
        directory.createdirectory(path);
      }

      string filename = path.getfilename(url);
      if (filename.indexof("?") > 0)
      {
        return path + "\\" + filename.substring(0, filename.indexof("?"));
      }
      else
      {
        return path + "\\" + filename;
      }
    }
    #endregion

  } //end form1类
}

测试截图:

C#限速下载网络文件的方法实例

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持。