多线程,分块下载。
using System;
using System.Collections.Generic;
using System.Text;
using System.Net;
using System.IO;
using System.Threading;
namespace prjDownLoad
{
class Program
{
//准备了一个用来保存的文件流。
static FileStream fs;
static void Main(string[] args)
{
Thread t = new Thread(new ThreadStart(Down));
t.Start();
}
static void Down()
{
fs = new FileStream("c:\\ee.pptx", FileMode.Create, FileAccess.Write);
DownloadUtil du = new DownloadUtil();
//订阅事件
du.DownloadCompleted += new DownloadCompletedHandler(du_DownloadCompleted);
du.DownloadProgress += new DownloadProgressHandler(du_DownloadProgress);
//多线程
byte[] bs = du.DownloadData("http://mschnlnine.vo.llnwd.net/d1/pdc08/PPTX/BB01.pptx");
////单线程
//byte[] bs = du.DownloadData("http://blog.sina.com.cn/dalishuishou");
Console.WriteLine(bs.Length);
fs.Write(bs, 0, bs.Length);
fs.Flush();
fs.Close();
}
/// <summary>
/// 下载过程事件处理过程
/// </summary>
/// <param name="bs"></param>
static void du_DownloadProgress(byte[] bs)
{
Console.WriteLine("下载了{0}字节",bs.Length);
}
/// <summary>
/// 下载完成事件处理过程
/// </summary>
static void du_DownloadCompleted()
{
Console.WriteLine("下载完成了。");
}
}
}
using System;
using System.Collections.Generic;
using System.Text;
namespace prjDownLoad
{
//下载完成委托
public delegate void DownloadCompletedHandler();
}
using System;
using System.Collections.Generic;
using System.Text;
namespace prjDownLoad
{
//下载过程委托
public delegate void DownloadProgressHandler(byte[] bs);
}
using System;
using System.Collections.Generic;
using System.Text;
namespace prjDownLoad
{
/// <summary>
/// 下载的数据块
/// </summary>
[Serializable]
public class DownloadChunk
{
//临时存储的集合
List<byte> content = new List<byte>();
/// <summary>
/// 整个块的内容
/// </summary>
public byte[] Content
{
get { return content.ToArray(); }
}
/// <summary>
/// 向块中添加内容
/// </summary>
/// <param name="bs"></param>
public void AddContent(byte[] bs)
{
content.AddRange(bs);
}
int from;
/// <summary>
/// 开始位置
/// </summary>
public int From
{
get { return from; }
set { from = value; }
}
int to;
/// <summary>
/// 结束位置
/// </summary>
public int To
{
get { return to; }
set { to = value; }
}
int number;
/// <summary>
/// 块编号
/// </summary>
public int Number
{
get { return number; }
set { number = value; }
}
}
}
using System;
using System.Collections.Generic;
using System.Text;
using System.IO;
using System.Net;
namespace prjDownLoad
{
/// <summary>
/// 下载信息实体类
/// </summary>
[Serializable]
public class DownloadInfo
{
DownloadChunk downloadChunk;
public DownloadChunk DownloadChunk
{
get { return downloadChunk; }
set { downloadChunk = value; }
}
WebRequest webRequest;
/// <summary>
/// 这个WebRequest中如果是分块下载
/// 那么在Range中要加上开始和结束位置
/// </summary>
public WebRequest WebRequest
{
get { return webRequest; }
set { webRequest = value; }
}
Stream readStream;
/// <summary>
/// 读取数据的流
/// </summary>
public Stream ReadStream
{
get { return readStream; }
set { readStream = value; }
}
byte[] buffer = new byte[1024];
/// <summary>
/// 缓冲字节数组,用来存储从流中读取的数据的容器
/// </summary>
public byte[] Buffer
{
get { return buffer; }
set { buffer = value; }
}
}
}
using System;
using System.Collections.Generic;
using System.Text;
using System.Threading;
using System.Net;
using System.IO;
namespace prjDownLoad
{
public class DownloadUtil
{
//固定为5个线程
const int ThreadSum = 5;
//线程数组
Thread[] ts=new Thread[ThreadSum];
//已经完成的线程个数
int threadCount;
//多线程下载时的容器
byte[] allChunkContent;
//信号机
AutoResetEvent autoResetEvent=new AutoResetEvent(false);
/// <summary>
/// 下载完成事件
/// </summary>
public event DownloadCompletedHandler DownloadCompleted;
/// <summary>
/// 下载过程事件
/// </summary>
public event DownloadProgressHandler DownloadProgress;
//临时保存字节数组的集合(单线程下载时使用)
List<byte> bytes = new List<byte>();
//要存储的fileName
string fileName;
/// <summary>
/// 下载数据
/// </summary>
/// <param name="url">要下载的url</param>
/// <param name="fileName">要保存的文件名</param>
/// <returns>下载完成的byte数组</returns>
public byte[] DownloadData(string url,string fileName)
{
this.fileName = fileName;
long length=GetLength(url);
if (length==-1)
{
WebRequest wr = WebRequest.Create(url);
wr.BeginGetResponse(new AsyncCallback(GetResponseCallBack), wr);
autoResetEvent.WaitOne();
if (fileName != "")
{
FileStream fs = new FileStream(fileName, FileMode.Create, FileAccess.Write);
fs.Write(bytes.ToArray(), 0, bytes.ToArray().Length);
fs.Flush();