c# Http下载器

一、简述

     记--简单的http下载器,支持断点续传、计算下载网速、剩余时间、用时、平均网速。

例子打包:https://wwa.lanzous.com/iKQzue5h8xc

二、效果

三、工程结构

四、源文件

HttpHelper.cs文件

/** 类名:HttpHelper* 描述:Http下载帮助类* 功能:*      1. 断点续传*      2. 可暂停下载*      3. 计算下载速度、下载剩余时间、下载用时* 作者:Liang* 版本:V1.0.1* 修改时间:2020-06-29*/
using System;
using System.IO;
using System.Net;namespace HttpDownload
{public enum eDownloadSta{STA_NUL,//没有下载任务STA_START,//开始下载STA_ING,//下载中STA_PAUSE,//暂停下载STA_CONTINUE,//继续下载STA_STOP,//停止下载STA_FINISH,//下载完成STA_ERR//下载出错}class HttpHelper{//定时器间隔 与下载速度的计算有关const int TIMER_TICK = 1000;//每秒计算一次网速//接收数据的缓冲区const int BUF_SIZE = 8*1024;//最大读取错误数,达到之后会出下载const int READ_ERR_MAX_CNT = 3;/// <summary>/// 下载数据更新/// </summary>/// <param name="totalNum">下载文件总大小</param>/// <param name="curSize">已下载文件大小</param>/// <param name="speed">下载速度</param>/// <param name="mRemainTime">剩余下载时间</param>public delegate void delegateDownProcess(double curSize, double speed, uint mRemainTime, uint spanTime, eDownloadSta sta);public delegateDownProcess process;//文件大小public delegate void delegateFileSize(double fileSize);public delegateFileSize downFileSize;//定时器,定时将下载进度等信息发送给UI线程public System.Timers.Timer mTimer = null;private double mFileSize;//文件大小private double mCurReadSize;//已下载大小private double mOneSecReadSize;//1秒下载大小private double mSpeed;//下载速度private uint mRemainTime;//剩余下载时间private uint mTotalTimeSec = 0;//下载总时间 单位:秒private eDownloadSta mCurDownloadSta;//当前下载状态string mSaveFileName = "";//文件保存名称string mHttpUrl = "";//http下载路径public HttpHelper(){ }//务必使用此函数初始化,因为定时器需要再主类创建public HttpHelper(System.Timers.Timer _timer, delegateDownProcess processShow, delegateFileSize downloadFileSize){if (mTimer == null){mTimer = _timer;mTimer.Interval = TIMER_TICK;mTimer.Stop();mTimer.Elapsed += new System.Timers.ElapsedEventHandler(tickEventHandler); //到达时间的时候执行事件;   mTimer.AutoReset = true;   //设置重复执行(true);  mTimer.Enabled = true;     //设置执行tickEventHandler事件this.process += processShow;this.downFileSize += downloadFileSize;}init();mCurDownloadSta = eDownloadSta.STA_FINISH;}public void init(){mFileSize = 0.0;mCurReadSize = 0.0;mOneSecReadSize = 0.0;mSpeed = 0.0;mRemainTime = 0;mTotalTimeSec = 0;}/// <summary>///格式化文件大小,格式化为合适的单位/// </summary>/// <param name="size">字节大小</param>/// <returns></returns>public static string formateSize(double size){string[] units = new string[] { "B", "KB", "MB", "GB", "TB", "PB" };double mod = 1024.0;int i = 0;while (size >= mod){size /= mod;i++;}return size.ToString("f2") + units[i];}/// <summary>/// 将秒数格式化为 时分秒格式/// </summary>/// <param name="second"></param>/// <returns></returns>public static string formatTime(uint second){//return new DateTime(1970, 01, 01, 00, 00, 00).AddSeconds(second).ToString("HH:mm:ss");uint hour = second / 3600;uint tmp1 = second - hour * 3600;uint min = tmp1 / 60;uint sec = tmp1 - min * 60;return string.Format("{0}:{1}:{2}", hour.ToString("00"), min.ToString("00"), sec.ToString("00"));}/// <summary>/// 下载文件(同步)  支持断点续传/// </summary>public int dowLoadFile(){            int errCnt = 0;            //打开上次下载的文件或新建文件long startPos = 0;FileStream fs = null;if (File.Exists(mSaveFileName))//文件已经存在就继续下载{try{fs = File.OpenWrite(mSaveFileName);if (null == fs){Console.WriteLine("open file failed:" + mSaveFileName);return -1;}startPos = fs.Length;}catch(Exception e){Console.WriteLine("open file err:"+e.Message);if (null != fs){fs.Close();return -2;}}}else//新文件{fs = new FileStream(mSaveFileName, FileMode.Create);Console.WriteLine("创建文件");startPos = 0;}/**获取文件大小**/HttpWebRequest request = (HttpWebRequest)WebRequest.Create(mHttpUrl);if (null == request){return -3;}request.UserAgent = "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/68.0.3440.106 Safari/537.36";//request.KeepAlive = true;//保持连接//设置Range值,请求指定位置开始的数据,实现断点续传            request.AddRange(startPos);//request.AddRange(startPos, endPos)获取指定范围数据,续传跟重传(中间某部分)可使用该函数WebResponse respone = null;//注:断点续传必须在request后、并设置AddRange后第一次获取的Response才是正确的数据流try{respone = request.GetResponse();if (null == respone){request.Abort();fs.Close();return -4;}}catch (Exception e){Console.WriteLine("getResponse err:"+e.Message);fs.Close();return -4;}mFileSize = Convert.ToDouble(respone.ContentLength) + startPos;            //发送文件大小downFileSize?.Invoke(mFileSize);if (mFileSize < 0){Console.WriteLine("获取文件大小失败");return -5;}//文件错误,清空文件if (mFileSize < startPos){fs.SetLength(0);//截断文件,相当于是清空文件内容Console.WriteLine("文件错误,清空后重新下载");}mCurReadSize = startPos;//文件已下载if (mCurReadSize >= mFileSize){fs.Close();respone.Close();request.Abort();Console.WriteLine("文件已经下载");return 0;}fs.Seek(startPos, SeekOrigin.Begin);   //移动文件流中的当前指针//Console.WriteLine("startPos:{0}", startPos);Stream responseStream = null;byte[] dataBuf = new byte[BUF_SIZE];//打开网络连接try{//向服务器请求,获得服务器回应数据流responseStream = respone.GetResponseStream();if (null == responseStream){fs.Close();respone.Close();request.Abort();return -6;}             int nReadSize = 0;do{//读取数据nReadSize = responseStream.Read(dataBuf, 0, BUF_SIZE);if (nReadSize > 0){fs.Write(dataBuf, 0, nReadSize);//此处应该判断是否写入成功//已下载大小mCurReadSize += nReadSize;mOneSecReadSize += nReadSize;}else{errCnt++;if (errCnt > READ_ERR_MAX_CNT){Console.WriteLine("下载出错,退出下载");break;}}if (mCurDownloadSta == eDownloadSta.STA_STOP){Console.WriteLine("停止下载");break;}} while (mCurReadSize<mFileSize);responseStream.Close();respone.Close();fs.Close();request.Abort();//Console.WriteLine("mCurReadSize:{0}, mFileSize:{1}", mCurReadSize, mFileSize);if (mCurReadSize == mFileSize)//下载完成{Console.WriteLine("下载完成");return 100;}return 1;}catch (Exception ex)//下载失败{responseStream.Close();respone.Close();fs.Close();request.Abort();Console.WriteLine("下载失败:" + ex.ToString());return -7;}        }//停止下载public void downloadStop(){mCurDownloadSta = eDownloadSta.STA_STOP;mTimer.Stop();}/// <summary>/// 开始下载/// </summary>/// <param name="url">下载url</param>/// <param name="fileName">保存文件名</param>public void download(string url, string fileName){if(mCurDownloadSta == eDownloadSta.STA_ING){Console.WriteLine("url:{0} is downloading...", url);return;}if (mHttpUrl != url)//新的下载文件要重新计数{init();}else{mFileSize = 0.0;mCurReadSize = 0.0;mOneSecReadSize = 0.0;mRemainTime = 0;}mHttpUrl = url;mSaveFileName = fileName;if (fileName.Length<1){mSaveFileName = Directory.GetCurrentDirectory() + Path.GetFileName(url);}mCurDownloadSta = eDownloadSta.STA_START;//Task.Run(() =>//{//});mTimer.Start();mCurDownloadSta = eDownloadSta.STA_ING;Console.WriteLine("start download:");int ret = -1;try{ret = dowLoadFile();}catch(Exception e){ret = -100;Console.WriteLine("dowload err, err:"+e.Message);                    }mCurDownloadSta = eDownloadSta.STA_FINISH;mTimer.Stop();if (ret < 0){process?.Invoke(mFileSize, mFileSize, 0, 0, eDownloadSta.STA_ERR);}else if (ret == 0){process?.Invoke(mFileSize, mFileSize, 0, 0, eDownloadSta.STA_FINISH);}else{process?.Invoke(mCurReadSize, mSpeed, mRemainTime, mTotalTimeSec, eDownloadSta.STA_FINISH);} }/// <summary>/// 定时器方法 定时将下载进度和速度和剩余时间发送出去/// </summary>/// <param name="sender"></param>/// <param name="e"></param>private void tickEventHandler(object sender, EventArgs e){if (mCurDownloadSta == eDownloadSta.STA_ING){mTotalTimeSec++;//下载速度 1秒内下载大小/1秒mSpeed = mOneSecReadSize;mOneSecReadSize = 0;//剩余时间 剩余大小/速度 单位:秒if (mSpeed != 0){mRemainTime = (uint)((mFileSize - mCurReadSize) / mSpeed);}else{mRemainTime = 0;}process?.Invoke(mCurReadSize, mSpeed, mRemainTime, mTotalTimeSec, eDownloadSta.STA_ING);}}        }
}

Form1.cs文件

using System;
using System.IO;
using System.Threading;
using System.Windows.Forms;namespace HttpDownload
{public partial class Form1 : Form{private string mSaveFileName = "";//下载文件的保存文件名      string curPath = "";//应用当前目录HttpHelper mHttpHelper = null;public delegate void DelegateProcessShow(double curSize, double speed, uint remainTime, uint spanTime, eDownloadSta sta);public delegate void DelegateSetFileSize(double val);private double mDownloadFileSize = 0.0;//文件大小private double mTotalSpd = 0.0;//用于计算平均速度uint mTotalSpdCnt = 0;//用于计算平均速度public Form1(){InitializeComponent();//应用当前目录curPath = AppDomain.CurrentDomain.BaseDirectory.ToString();//初始化Http下载对象initHttpManager();}//初始化Http下载对象private void initHttpManager(){if (null == mHttpHelper){mHttpHelper = new HttpHelper(new System.Timers.Timer(), processShow, downloadFileSize);}}/// <summary>/// 更新下载进度/// </summary>/// <param name="totalNum">文件总大小</param>/// <param name="num">已下载</param>/// <param name="proc">进度</param>/// <param name="speed">速度</param>/// <param name="remainTime">剩余时间</param>/// <param name="msg">消息</param>public void processShow(double curSize, double speed, uint remainTime, uint spanTime, eDownloadSta sta){if (this.InvokeRequired){DelegateProcessShow delegateprocShow = new DelegateProcessShow(processShow);this.Invoke(delegateprocShow, new object[] { curSize, speed, remainTime, spanTime, sta});}else{//Console.WriteLine("curSize:{0}, mDownloadFileSize:{1}", curSize, mDownloadFileSize);if (mDownloadFileSize < 0 || sta == eDownloadSta.STA_ERR){MessageBox.Show("下载出错!请删除"+ mSaveFileName + ",并重新尝试!", "错误", MessageBoxButtons.OK, MessageBoxIcon.Error);mHttpHelper.downloadStop();buttonDownload.Text = "下载";textBoxHttpUrl.Enabled = true;}else if (mDownloadFileSize > 0){labelDownSize.Text = "已下载:" + HttpHelper.formateSize(curSize);int proc = 0;mTotalSpdCnt++;mTotalSpd += speed;if (curSize < mDownloadFileSize){proc = (int)((curSize / mDownloadFileSize) * 100);}else if (curSize == mDownloadFileSize){proc = progressBarDownloadFile.Maximum;}else{mHttpHelper.downloadStop();buttonDownload.Text = "下载";textBoxHttpUrl.Enabled = true;                        MessageBox.Show("文件续传出错!", "错误", MessageBoxButtons.OK, MessageBoxIcon.Error);}                  this.labelProcess.Text = string.Format("{0}%", proc);progressBarDownloadFile.Value = proc;this.labelDownSpd.Text = string.Format("速度:{0}/s", HttpHelper.formateSize(speed));this.labelDownNeedTime.Text = string.Format("剩余时间:{0}", HttpHelper.formatTime(remainTime));this.labelSpanTime.Text = string.Format("用时:{0}", HttpHelper.formatTime(spanTime));if (proc == progressBarDownloadFile.Maximum){mHttpHelper.downloadStop();buttonDownload.Text = "下载";textBoxHttpUrl.Enabled = true;this.labelProcess.Text = "100%";progressBarDownloadFile.Value = proc;labelAvgSpd.Visible = true;labelAvgSpd.Text = string.Format("均速:{0}/s", HttpHelper.formateSize((mTotalSpd / mTotalSpdCnt)));//Console.WriteLine("finish:" + DateTime.Now.ToString("yyyyMMdd-HHmmss"));MessageBox.Show("存放路径:" + curPath + mSaveFileName, "下载完成", MessageBoxButtons.OK, MessageBoxIcon.Information);}                   }}}//下载文件大小void downloadFileSize(double fileSize){if (this.InvokeRequired){DelegateSetFileSize delegateSetFileSize = new DelegateSetFileSize(downloadFileSize);this.Invoke(delegateSetFileSize, new object[] { fileSize });}else{if (fileSize > 0){this.labelFileSizeTotal.Text = "文件大小:" + HttpHelper.formateSize(fileSize);mDownloadFileSize = fileSize;}else if (fileSize < 0){MessageBox.Show("获取文件长度出错!", "错误");}}}private void Form1_Load(object sender, EventArgs e){//测试使用,这是tx软件中心的qq最新的下载链接,https://dl.softmgr.qq.com/original/im/QQ9.3.5.27030.exe//如果链接失效请自行获取或再找一个链接textBoxHttpUrl.Text = "https://dl.softmgr.qq.com/original/im/QQ9.3.5.27030.exe"; //"请输入http下载地址";}//下载private void download(string httpUrl, string saveFileName){mHttpHelper.download(httpUrl, mSaveFileName);}private void buttonDownload_Click(object sender, EventArgs e){if (buttonDownload.Text == "下载"){//获取http下载路径string httpUrl = textBoxHttpUrl.Text.Trim();if (!httpUrl.StartsWith("http://") && !httpUrl.StartsWith("https://")){MessageBox.Show("请输入正确的http下载链接!", "提示");textBoxHttpUrl.Focus();//url地址栏获取焦点return;}mSaveFileName = Application.StartupPath + "\\" + Path.GetFileName(httpUrl);progressBarDownloadFile.Value = 0;buttonDownload.Text = "停止";labelProcess.Text = "0%";mTotalSpd = 0.0;mTotalSpdCnt = 0;labelAvgSpd.Visible = false;textBoxHttpUrl.Enabled = false;//Console.WriteLine("start:"+DateTime.Now.ToString("yyyyMMdd-HHmmss"));new Thread(() => download(httpUrl, mSaveFileName)).Start(); //开启下载线程}else//停止{buttonDownload.Text = "下载";textBoxHttpUrl.Enabled = true;mHttpHelper.downloadStop();}}}
}

五、待完善

5.1 待完善细节

5.2 多线程下载

5.3 模拟浏览器下载非直链、网盘文件

六、附

例子中的http链接时是当时QQ新版本下载地址:https://dl.softmgr.qq.com/original/im/QQ9.3.5.27030.exe

c# Http下载器相关推荐

  1. macos下使用aria2_用Aria2代替Firefox内置的下载器

    本方案代替了火狐弱鸡的下载器,使用aria2来接管火狐的下载工具.不需要额外安装其他的东西. 首先需要下载aria2的本体,去GitHub上拖下来: https://github.com/aria2/ ...

  2. [C# 网络编程系列]专题十一:实现一个基于FTP协议的程序——文件上传下载器...

    引言: 在这个专题将为大家揭开下FTP这个协议的面纱,其实学习知识和生活中的例子都是很相通的,就拿这个专题来说,要了解FTP协议然后根据FTP协议实现一个文件下载器,就和和追MM是差不多的过程的,相信 ...

  3. Android通用简洁的下载器

    下载逻辑在android开发中可谓很常见,那么封装一个通用简洁的下载器时很有必要的.如果不想给工程引入一个很重的jar包那么可以直接复用下面的代码即可. 主要对外接口 构造函数 :     publi ...

  4. 冰点文库下载器停止工作解决办法

    冰点文库下载器停止工作解决办法 最近在使用冰点文库下载器下载文档的时候出现冰点文库下载器停止工作的问题,在下载文档之后,只要开始转换就出现提示,下面小编为大家分享解决办法! 冰点文库下载器停止工作问题 ...

  5. atmel c keil 包_Keil C软件与AVR Atmega系列下载器使用

    Keil 作为电子工程师首选,因为他目前通吃C51和STM32的开发平台. 51单片机是8位单片机(AT89C51与STC89C51与AT89S51),AVR Atmega也是属于8位(Atmega3 ...

  6. 利用CH340C制作MicroPython ESP8266,ESP32的下载器-改进型

    简 介: 本文给出了利用CH340C芯片制作ESP32,ESP8266下载器的方法,并进行了实测测试. 关键词: ESP32,CH340C,MicroPython,下载器 ▌01 ESP的MicroP ...

  7. 测试CH340C的功能,制作MicroPython ESP8266,ESP32下载器

    ▌01 CH340C USB-UART芯片 CH340C 是沁恒公司的USB-UART的转换芯片.在 CH340E USB转串口 IC测试电路 测试了CH340E的基本功能.为了制作 ESP8266以 ...

  8. 制作新版STC单片机WiFi下载器

    简 介: 基于WiFi的STC单片机下载器可以方便对STC的8A,8G,8H,15系列的单片机完成程序下载,方便了程序的开发与调试.特别适应于需要强磁隔离.运动平台的单片机开发,做到程序的快速更新与测 ...

  9. 远洋整站下载器不能用https_这可能是最全最好的爆破百度文库下载指南了!

    日常生活中,无论各行各业,我相信,你一定用过某下载文档资料的平台,比如说,百度文库. 有时候,为了赶交一篇论文或者下载一些考试真题,百度搜了半天资料,刚刚找到一个觉得蛮不错的打算下载,结果... 要么 ...

  10. 【源码分享】用Java写的网页图片、CSS、JavaScript分类下载器

    前段时间老师让我们要做一个JavaEE项目,是一个电子商务网站--中国鲜花网,前台模板就用这个网站的,但是用浏览器直接下载来的图片和样式表等文件全在一个文件夹,需要给它批量替换,最要命的是浏览器的这个 ...

最新文章

  1. IS服务器下做301永久重定向设置方法
  2. 如何配置LCD背光和LED,调试方法
  3. 表达式括号匹配(信息学奥赛一本通-T1353)
  4. python运维监控脚本_Python实现数通设备端口使用情况监控实例
  5. git 回退上一个版本
  6. nginx服务器怎么配置文件,nginx服务器搭建和配置(nginx怎么搭配配置服务器)
  7. python 基础 5 while循环语句
  8. python基础之列表生成式和生成器
  9. 酷柚易汛进销存开源版升级来啦
  10. 参加口碑最好的广州传智播客Java就业培训班吧
  11. 百度地图开发Sug检索Demo
  12. 虚拟机安装Linux(ubuntu)
  13. 时间片轮转算法的实现
  14. 如何让网站HTTPS评级为A或者A+
  15. 服务器虚拟主机玩魔域,服务器虚拟主机玩魔域
  16. 【RE】3 CRC校验原理及实现
  17. 用八叉树优化RayCasting
  18. 重采样 resample
  19. Vue.config.productionTip = false 是什麽意思?
  20. Configure hp 磁带库 Fibre Channel Card

热门文章

  1. !!Python基础认知学习课件
  2. 百度图片源码流出~按照颜色搜图片~提取图片主体颜色
  3. python解释器源码 pdf_《python解释器源码剖析》第0章--python的架构与编译python
  4. android 实现 3d 文字,android 3d 游戏 开发 基础 第10课-2D文字显示.ppt
  5. 深入浅出计算机组成原理 通过CPU主频看性能(自我提升第8天)
  6. 跳棋游戏(求最大升序子序列和)
  7. cadence导入dxf文件_Allegro中导入导出DXF文件
  8. 【java表达式引擎】一、汇总目前开源的公式计算开源库
  9. 飞机是最不安全的交通工具吗?
  10. 【c语言】:文件管理