补丁更新服务器二(多线程下载+进度条)
- -为了做补丁服务器就差这个下载,所以就做了这个- -测试用
https://files.cnblogs.com/ajaxren/DowonFile2008_07_27.rar 原代码用2008写的
界面,同时下栽两个(我的图画的好差啊)
newDownFile--下载类
newDownFile.ExecDown(ABDownFileChange inputDownFileChange)开始下载
/// <summary>
/// 更改通知进度条
/// </summary>
public class DownFileChangeProgressBar: ABDownFileChange
/// <summary>
/// 不需要更改通知
/// </summary>
public class DownFileNoChange: ABDownFileChange
--------------------下面的代码注意看注释啊
using System;
using System.Drawing;
using System.Collections;
using System.ComponentModel;
using System.Windows.Forms;
using System.Data;
using System.Net;
using System.IO;
using System.Threading;
namespace DowonFile
{
/// <summary>
/// 新的下载类
/// </summary>
public class newDownFile
{
/// <summary>
/// 下载文件的信息
/// </summary>
WebClient DownWebClientCurrent = new WebClient();
/// <summary>
///
/// </summary>
public newDownFile()
{
}
/// <summary>
/// 开始下载
/// </summary>
public void ExecDown(ABDownFileChange inputDownFileChange)
{
Thread th = new Thread(new ParameterizedThreadStart(DownFileManagement));
//--设置为后台主线程
th.IsBackground = true;
th.Start(inputDownFileChange);
}
/// 下载文件的管理者
/// </summary>
private void DownFileManagement(object InputDownFIleInfo)
{
ABDownFileChange ThreadDownFIleInfo = InputDownFIleInfo as ABDownFileChange;
string _DownUrl = ThreadDownFIleInfo.DownUrl;
string _saveFile = ThreadDownFIleInfo.SaveFile;
long fbytes;
if (_saveFile != "")
{
//---确定文件的长度
fbytes = this.GetDownFileCount(ThreadDownFIleInfo.DownUrl);
//-----读取不了
if (fbytes == -1)
{//--当可以通知的时候
if (ThreadDownFIleInfo.isChange)
ThreadDownFIleInfo.Error("错误");
return;
}
//-----------------------------下载对象,--------- 下载长度
byte[] mbyte = this.DownFile(ThreadDownFIleInfo, fbytes);
this.SaveFile(mbyte, _saveFile);
}
}
object l = new object();
/// <summary>
/// 开始下载
/// </summary>
/// <returns></returns>
private byte[] DownFile( ABDownFileChange inputDownFileChange,long fbytes)
{
Stream strm = null;
//--这里的锁是必须的否则-在多线程访问的时候会有 i/o错误
lock(l)
{
strm= DownWebClientCurrent.OpenRead(inputDownFileChange.DownUrl);
}
StreamReader reader = new StreamReader(strm, System.Text.Encoding.GetEncoding("gb2312"));
byte[] mbyte = new byte[fbytes];
int allmybyte = (int)mbyte.Length;
int startmbyte = 0;
////--准许通知首先设置长度
//if (inputDownFileChange.isChange)
// inputDownFileChange.setCount(allmybyte, true);
while (fbytes > 0)
{
int m = strm.Read(mbyte, startmbyte, allmybyte);
if (m == 0) break;
startmbyte += m;
allmybyte -= m;
//--准许通知,---开始发送更改通知
if (inputDownFileChange.isChange)
inputDownFileChange.Change(m,(int)mbyte.Length);
}
strm.Close();
return mbyte;
}
/// <summary>
/// 得到文件的长度
/// </summary>
/// <returns></returns>
public long GetDownFileCount(string _DownUrl)
{
WebRequest wr_request = WebRequest.Create(_DownUrl);
WebResponse wr_response = wr_request.GetResponse();
long fbytes = wr_response.ContentLength;
wr_response.Close();
return fbytes;
}
/// <summary>
/// 保存文件
/// </summary>
public void SaveFile(byte[] mbyte, string _saveFile)
{
FileStream fstrm = new FileStream(_saveFile, FileMode.OpenOrCreate, FileAccess.Write);
fstrm.Write(mbyte, 0, mbyte.Length);
fstrm.Close();
}
}
}
using System.Drawing;
using System.Collections;
using System.ComponentModel;
using System.Windows.Forms;
using System.Data;
using System.Net;
using System.IO;
using System.Threading;
namespace DowonFile
{
/// <summary>
/// 新的下载类
/// </summary>
public class newDownFile
{
/// <summary>
/// 下载文件的信息
/// </summary>
WebClient DownWebClientCurrent = new WebClient();
/// <summary>
///
/// </summary>
public newDownFile()
{
}
/// <summary>
/// 开始下载
/// </summary>
public void ExecDown(ABDownFileChange inputDownFileChange)
{
Thread th = new Thread(new ParameterizedThreadStart(DownFileManagement));
//--设置为后台主线程
th.IsBackground = true;
th.Start(inputDownFileChange);
}
/// 下载文件的管理者
/// </summary>
private void DownFileManagement(object InputDownFIleInfo)
{
ABDownFileChange ThreadDownFIleInfo = InputDownFIleInfo as ABDownFileChange;
string _DownUrl = ThreadDownFIleInfo.DownUrl;
string _saveFile = ThreadDownFIleInfo.SaveFile;
long fbytes;
if (_saveFile != "")
{
//---确定文件的长度
fbytes = this.GetDownFileCount(ThreadDownFIleInfo.DownUrl);
//-----读取不了
if (fbytes == -1)
{//--当可以通知的时候
if (ThreadDownFIleInfo.isChange)
ThreadDownFIleInfo.Error("错误");
return;
}
//-----------------------------下载对象,--------- 下载长度
byte[] mbyte = this.DownFile(ThreadDownFIleInfo, fbytes);
this.SaveFile(mbyte, _saveFile);
}
}
object l = new object();
/// <summary>
/// 开始下载
/// </summary>
/// <returns></returns>
private byte[] DownFile( ABDownFileChange inputDownFileChange,long fbytes)
{
Stream strm = null;
//--这里的锁是必须的否则-在多线程访问的时候会有 i/o错误
lock(l)
{
strm= DownWebClientCurrent.OpenRead(inputDownFileChange.DownUrl);
}
StreamReader reader = new StreamReader(strm, System.Text.Encoding.GetEncoding("gb2312"));
byte[] mbyte = new byte[fbytes];
int allmybyte = (int)mbyte.Length;
int startmbyte = 0;
////--准许通知首先设置长度
//if (inputDownFileChange.isChange)
// inputDownFileChange.setCount(allmybyte, true);
while (fbytes > 0)
{
int m = strm.Read(mbyte, startmbyte, allmybyte);
if (m == 0) break;
startmbyte += m;
allmybyte -= m;
//--准许通知,---开始发送更改通知
if (inputDownFileChange.isChange)
inputDownFileChange.Change(m,(int)mbyte.Length);
}
strm.Close();
return mbyte;
}
/// <summary>
/// 得到文件的长度
/// </summary>
/// <returns></returns>
public long GetDownFileCount(string _DownUrl)
{
WebRequest wr_request = WebRequest.Create(_DownUrl);
WebResponse wr_response = wr_request.GetResponse();
long fbytes = wr_response.ContentLength;
wr_response.Close();
return fbytes;
}
/// <summary>
/// 保存文件
/// </summary>
public void SaveFile(byte[] mbyte, string _saveFile)
{
FileStream fstrm = new FileStream(_saveFile, FileMode.OpenOrCreate, FileAccess.Write);
fstrm.Write(mbyte, 0, mbyte.Length);
fstrm.Close();
}
}
}
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace DowonFile
{
/// <summary>
/// 当发生更改的时候通知的类
/// </summary>
public abstract class ABDownFileChange
{
public string DownUrl;// = _downUrl;
public string SaveFile;// = _saveFile;
/// <summary>
/// 是否通知
/// </summary>
public bool isChange = false;
/// <summary>
/// 不通知
/// </summary>
public ABDownFileChange()
{
}
/// <summary>
/// 自有设定true是通知
/// </summary>
/// <param name="inputIsChange"></param>
public ABDownFileChange(bool inputIsChange)
{
isChange = inputIsChange;
}
/// <summary>
///设置更改
/// </summary>
/// <param name="number"></param>
public abstract void Change(int number, int count);
/// <summary>
/// 错误通知
/// </summary>
/// <param name="message"></param>
public abstract void Error(string message);
}
}
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace DowonFile
{
/// <summary>
/// 当发生更改的时候通知的类
/// </summary>
public abstract class ABDownFileChange
{
public string DownUrl;// = _downUrl;
public string SaveFile;// = _saveFile;
/// <summary>
/// 是否通知
/// </summary>
public bool isChange = false;
/// <summary>
/// 不通知
/// </summary>
public ABDownFileChange()
{
}
/// <summary>
/// 自有设定true是通知
/// </summary>
/// <param name="inputIsChange"></param>
public ABDownFileChange(bool inputIsChange)
{
isChange = inputIsChange;
}
/// <summary>
///设置更改
/// </summary>
/// <param name="number"></param>
public abstract void Change(int number, int count);
/// <summary>
/// 错误通知
/// </summary>
/// <param name="message"></param>
public abstract void Error(string message);
}
}
using System;
using System.Drawing;
using System.Collections;
using System.ComponentModel;
using System.Windows.Forms;
using System.Data;
using System.Net;
using System.IO;
using System.Threading;
namespace DowonFile
{
/// <summary>
/// 更改
/// </summary>
public class DownFileChangeProgressBar : ABDownFileChange
{
private System.Windows.Forms.ProgressBar _progressBar;
/// <summary>
/// 线程用到的委托
/// </summary>
/// <param name="value"></param>
delegate void StringParameterDelegate(int number,int count);
public DownFileChangeProgressBar(System.Windows.Forms.ProgressBar InputProgressBar):base(true)
{
this._progressBar = InputProgressBar;
}
/// <summary>
///设置更改
/// </summary>
/// <param name="number"></param>
public override void Change(int number, int count)
{
//--判断是否在ui线程中工作哦
if (this._progressBar.InvokeRequired)
{
//--这里不可以用BeginInvoke,虽然 BeginInvoke速度快,但是多次调用会出现此线程坏死的错误,应该用Invoke
// We're not in the UI thread, so we need to call BeginInvoke
this._progressBar.Invoke(new StringParameterDelegate(this.Change), new object[] { number,count });
return;
}
// Must be on the UI thread if we've got this far,如果在直接设置
this._progressBar.Maximum = count;
this._progressBar.Value += number;
}
/// <summary>
/// 错误通知
/// </summary>
/// <param name="message"></param>
public override void Error(string message)
{
MessageBox.Show(message);
}
}
}
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace DowonFile
{
/// <summary>
/// 不需要更改通知
/// </summary>
public class DownFileNoChange: ABDownFileChange
{
public DownFileNoChange()
{
}
/// <summary>
///设置更改
/// </summary>
/// <param name="number"></param>
public override void Change(int number, int count)
{
}
/// <summary>
/// 错误通知
/// </summary>
/// <param name="message"></param>
public override void Error(string message)
{
}
}
}
----------------------------------调用
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
namespace DowonFile
{
public partial class test4 : Form
{
//--新的下载类
newDownFile n = new newDownFile();
public test4()
{
InitializeComponent();
}
private void button1_Click(object sender, EventArgs e)
{
//--这个乡当与下载参数
DownFileChangeProgressBar dfcpb = new DownFileChangeProgressBar(this.progressBar1);
saveFileDialog.ShowDialog();
dfcpb.DownUrl = this.textBox1.Text;
dfcpb.SaveFile=this.saveFileDialog.FileName;
n.ExecDown(dfcpb);
}
private void button2_Click(object sender, EventArgs e)
{
//newDownFile n = new newDownFile();
DownFileChangeProgressBar dfcpb = new DownFileChangeProgressBar(this.progressBar2);
saveFileDialog.ShowDialog();
dfcpb.DownUrl = this.textBox2.Text;
dfcpb.SaveFile = this.saveFileDialog.FileName;
n.ExecDown(dfcpb);
}
}
}
看到这里在说说扩展,比如断点续传,首先要记录断开的位置,其次,保存下载的数据,然后第二次下载的时候需要从段开的地方读数据,最后在合并就可以了