此实例主要是通过 System.Net.HttpWebRequest 和 System.Net.HttpWebResponse 来实现网络文件的下载
并通过事件返回下载进度信息(启用后台线程进行下载)
项目结构:
项目中包含:
下载类:Downloader.cs (用于启动线程下载文件,并返回相应的事件)
下载文件信息类:FileInfo.cs(记录要下载的文件信息,包括:文件名称、文件下载路径、文件大小...)
信息显示界面: Form1.cs 控制开始下载、显示下载进度信息,界面如图2
1.下载类 Downloader.cs 详情:
using System;using System.Collections.Generic;using System.Text;using System.Net;using System.Security.Cryptography.X509Certificates;using System.Net.Security;
namespace FileDownload{ /// <summary> /// 文件下载类 /// </summary> public class Downloader { public delegate void DelProInfoArg(FileInfo _file); public delegate void DeldownloadEndArg();
/// <summary> /// 开始下载文件,事件 /// </summary> public event DelProInfoArg DownloadStartingEvent; /// <summary> /// 分包下载 事件(通知显示更新进度) /// </summary> public event DelProInfoArg DownloadedEvent; /// <summary> /// 一个文件下载结束,事件 /// </summary> public event DelProInfoArg DownloadEndEvent; /// <summary> /// 所有的文件下载结束,事件 /// </summary> public event DeldownloadEndArg DownloadALLEnd;
private List<FileInfo> _waitDownloadFiles;
/// <summary>
/// 下载一批文件文件 /// </summary> /// <param name="list">文件列表</param> public Downloader(List<FileInfo> list) { _waitDownloadFiles = list; }
/// <summary>
/// 开始下载 /// </summary> public void Start() { System.Threading.Thread DownloadThread = new System.Threading.Thread(new System.Threading.ThreadStart(StartDownload)); DownloadThread.IsBackground = true; DownloadThread.Start(); }
/// <summary>
/// 线程启动,开始获取数据包 /// </summary> private void StartDownload() { if (_waitDownloadFiles != null && _waitDownloadFiles.Count > 0) {
int osize = 0;
foreach (FileInfo file in _waitDownloadFiles)
{ if (DownloadStartingEvent != null)//开始下载 { DownloadStartingEvent(file); } try { #region 此处加上这一段是为了能够正常下载https URL的文件,如果不加上这段服务器验证的回调并返回true,则下载https文件时会发生错误,会提示服务器无法通过验证,无法正常下载
ServicePointManager.ServerCertificateValidationCallback = new System.Net.Security.RemoteCertificateValidationCallback(ValidateServerCertificate);
#endregion
System.Net.HttpWebRequest Myrq = (System.Net.HttpWebRequest)System.Net.HttpWebRequest.Create(file.FileDownloadPath);
System.Net.HttpWebResponse myrp = (System.Net.HttpWebResponse)Myrq.GetResponse(); file.SumSize = myrp.ContentLength; System.IO.Stream st = myrp.GetResponseStream(); System.IO.Stream so = new System.IO.FileStream(file.FileSavePath, System.IO.FileMode.Create); byte[] by = new byte[1024];
osize = st.Read(by, 0, (int)by.Length);
while (osize > 0)
{ file.DownloadedSize = osize + file.DownloadedSize;
so.Write(by, 0, osize);
osize = st.Read(by, 0, (int)by.Length);
if (DownloadedEvent != null)//获取一段数据包,更新显示
{ DownloadedEvent(file); } } so.Close(); st.Close();
if (DownloadEndEvent != null)//一个文件下载完成
{ DownloadEndEvent(file); } } catch (Exception ex) { throw ex; } }
if (DownloadALLEnd != null)//下载结束
{ DownloadALLEnd(); } } else { if (DownloadALLEnd != null)//下载结束 { DownloadALLEnd(); } } }
/// <summary>
/// 自定义的服务器证书验证回调方法,这里始终认为存在证书可以下载,返回True /// </summary> /// <param name="sender"></param> /// <param name="certificate"></param> /// <param name="chain"></param> /// <param name="sslPolicyErrors"></param> /// <returns></returns> protected bool ValidateServerCertificate(object sender, X509Certificate certificate, X509Chain chain, SslPolicyErrors sslPolicyErrors) { return true; } }}
2.文件信息类 FileInfo.cs 详情:
using System;using System.Collections.Generic;using System.Text;
namespace FileDownload{ /// <summary> /// 需要下载的文件信息 /// </summary> public class FileInfo { /// <summary> /// 构造函数 /// </summary> /// <param name="_dowPath">下载路径</param> /// <param name="_savPath">文件保存路径</param> /// <param name="_fileName">文件名称</param> public FileInfo(string _dowPath, string _savPath, string _fileName) { fileDownloadPath = _dowPath; fileSavePath = _savPath; fileName = _fileName; }
/// <summary> /// 文件下载路径,http路径 /// </summary> private string fileDownloadPath; /// <summary> /// 文件下载路径,http路径 /// </summary> public string FileDownloadPath { get { return fileDownloadPath; } set { fileDownloadPath = value; } }
/// <summary> /// 文件存储路径,如D:\test\1.txt /// </summary> private string fileSavePath; /// <summary> /// 文件存储路径,如D:\test\1.txt /// </summary> public string FileSavePath { get { return fileSavePath; } set { fileSavePath = value; } } /// <summary> /// 文件名称 /// </summary> private string fileName; /// <summary> /// 文件名称 /// </summary> public string FileName { get { return fileName; } set { fileName = value; } } /// <summary> /// 文件总大小 /// </summary> private long sumSize; /// <summary> /// 文件总大小 /// </summary> public long SumSize { get { return sumSize; } set { sumSize = value; } } /// <summary> /// 已下载文件大小 /// </summary> private long downloadedSize; /// <summary> /// 已下载文件大小 /// </summary> public long DownloadedSize { get { return downloadedSize; } set { downloadedSize = value; } } }}
3.文件信息类 Form1.cs 详情:
using System;using System.Collections.Generic;using System.ComponentModel;using System.Data;using System.Drawing;using System.Text;using System.Windows.Forms;using System.IO;
namespace FileDownload{ public partial class Form1 : Form { public Form1() { InitializeComponent(); }
List<FileInfo> listfiles = null;
private void Form1_Load(object sender, EventArgs e) { LoadDownloadFileList(); }
/// <summary> /// 加载待下载的文件 /// </summary> private void LoadDownloadFileList() { string Strpath = System.AppDomain.CurrentDomain.BaseDirectory;//获得应用程序的基目录,即bin/release或debug目录中 listfiles = new List<FileInfo>();
#region 填充数据 FileInfo fileone = new FileInfo("", Path.Combine(Strpath, "文件1"), "文件1"); listfiles.Add(fileone);
FileInfo filetwo = new FileInfo("", Path.Combine(Strpath, "文件2"), "文件2"); listfiles.Add(filetwo); #endregion
ListViewItem item=null; foreach (FileInfo file in listfiles) { item=new ListViewItem (new string[]{file.FileName,file.FileDownloadPath,file.FileSavePath}); listView1.Items.Add(item); }
}
/// <summary> /// 开始下载 /// </summary> /// <param name="sender"></param> /// <param name="e"></param> private void btnStart_Click(object sender, EventArgs e) { Downloader download = new Downloader(listfiles); download.DownloadStartingEvent += new Downloader.DelProInfoArg(download_DownloadStartingEvent);//事件订阅,开始下载 download.DownloadedEvent += new Downloader.DelProInfoArg(download_DownloadedEvent);//事件订阅,新获取了数据表,更新显示 download.DownloadEndEvent += new Downloader.DelProInfoArg(download_DownloadEndEvent);//事件订阅,一个文件下载完成 download.DownloadALLEnd += new Downloader.DeldownloadEndArg(download_DownloadALLEnd);//事件订阅,所有的下载任务结束 download.Start(); }
#region 订阅事件,显示下载进度信息 void download_DownloadALLEnd() { if (this.InvokeRequired) { this.BeginInvoke(new DelShowArg(ShowDownloadingInfo), new object[] {"下载已结束",0,0 }); } else { ShowDownloadingInfo("下载已结束!", 0, 0); } }
void download_DownloadEndEvent(FileInfo _file) { int Downloaded =(int)_file.DownloadedSize / 1024; int ALLdownload = (int)_file.SumSize / 1024;
string strDownloadingInfo = string.Format("{0} 已下载完成!",_file.FileName); if (this.InvokeRequired) { this.BeginInvoke(new DelShowArg(ShowDownloadingInfo), new object[] { strDownloadingInfo, ALLdownload, Downloaded }); } else { ShowDownloadingInfo(strDownloadingInfo, ALLdownload, Downloaded); } }
void download_DownloadedEvent(FileInfo _file) { int Downloaded = (int)_file.DownloadedSize / 1024; int ALLdownload = (int)_file.SumSize / 1024;
string strDownloadingInfo = string.Format("{0} 正在下载中!", _file.FileName); if (this.InvokeRequired) { this.BeginInvoke(new DelShowArg(ShowDownloadingInfo), new object[] { strDownloadingInfo, ALLdownload, Downloaded }); } else { ShowDownloadingInfo(strDownloadingInfo, ALLdownload, Downloaded); } }
void download_DownloadStartingEvent(FileInfo _file) { int Downloaded = (int)_file.DownloadedSize / 1024; int ALLdownload = (int)_file.SumSize / 1024;
string strDownloadingInfo = string.Format("开始下载 {0}!", _file.FileName); if (this.InvokeRequired) { this.BeginInvoke(new DelShowArg(ShowDownloadingInfo), new object[] { strDownloadingInfo, ALLdownload, Downloaded }); } else { ShowDownloadingInfo(strDownloadingInfo, ALLdownload, Downloaded); } }
/// <summary> /// 自定义数据显示委托 /// </summary> /// <param name="_ShowInfo">显示的文字信息</param> /// <param name="_SumSize">总的数据包大小</param> /// <param name="_DownloadedSize">已下载数据包大小</param> private delegate void DelShowArg(string _ShowInfo, int _SumSize, int _DownloadedSize);
/// <summary> /// 显示下载进度信息 /// </summary> /// <param name="_ShowInfo">文字信息</param> /// <param name="_SumSize">总的数据包大小</param> /// <param name="_DownloadedSize">已下载大小</param> private void ShowDownloadingInfo(string _ShowInfo, int _SumSize, int _DownloadedSize) { lblProInfo.Text = _ShowInfo;
if (_SumSize != 0 && _DownloadedSize != 0) { Probar.Maximum = _SumSize; Probar.Minimum = 0; Probar.Value = _DownloadedSize;
lblPercent.Text = string.Format("{0}%", _DownloadedSize * 100 / _SumSize); } }
#endregion }}