为了解决那些个把下载过程中的byte数组,要拿去自行处理的变态们,俺特地做了下面的更改。
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)
{
fs = new FileStream("c:\\ee.txt", FileMode.Create, FileAccess.Write);
//在构造时可以不填写url和fileName
//在下载的时候再填写。
DownloadUtil du = new DownloadUtil();
//订阅事件
du.ReadCompleted += new ReadCompletedHandler(du_ReadCompleted);
du.ReadProgress += new ReadProgressHandler(du_ReadProgress);
//在下载的时候临时填写要下载的url
byte[] bs = du.DownloadData("http://blog.sina.com.cn/dalishuishou");
Console.WriteLine(bs.Length);
}
/// <summary>
/// 为嘛,读取过程事件只能返回一个字节个数呢?!
/// 能不能返回所读取的字节数组呢?
/// 当然可以。
/// </summary>
/// <param name="bs"></param>
static void du_ReadProgress(byte[] bs)
{
//既然都拿到了byte数组,呵呵
//你想咋处理,你咋处理。
//管俺屁事。
fs.Write(bs, 0, bs.Length);
fs.Flush();
Console.WriteLine("下载了{0}字节",bs.Length);
}
static void du_ReadCompleted()
{
//如果你要保存成文件,
//在完成后,应该关文件流了。
fs.Close();
Console.WriteLine("下载完成了。");
}
}
}
using System;
using System.Collections.Generic;
using System.Text;
namespace prjDownLoad
{
//读取完成委托
public delegate void ReadCompletedHandler();
}
using System;
using System.Collections.Generic;
using System.Text;
namespace prjDownLoad
{
//读取过程委托
public delegate void ReadProgressHandler(byte[] bs);
}
using System;
using System.Collections.Generic;
using System.Text;
using System.IO;
namespace prjDownLoad
{
/// <summary>
/// 下载信息实体类
/// </summary>
[Serializable]
public class DownloadInfo
{
Stream readSt;
/// <summary>
/// 读取数据的流
/// </summary>
public Stream ReadSt
{
get { return readSt; }
set { readSt = value; }
}
Stream writeSt;
/// <summary>
/// 写入数据的流
/// </summary>
public Stream WriteSt
{
get { return writeSt; }
set { writeSt = 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
{
//添加一个AutoResetEvent
//这是一个信号机
AutoResetEvent are=new AutoResetEvent(false);
//读取完成事件
public event ReadCompletedHandler ReadCompleted;
//读取过程事件
public event ReadProgressHandler ReadProgress;
//临时保存字节数组的集合。
List<byte> list = new List<byte>();
////只所以不把字段公开的原因是:
////告诉客户,你必须通过构造把
////地址和文件名传递进来,只有
////这一种方式,别想着等实例化
////以后再赋值。
////省的麻烦。
//string url;
//只保留fileName
string fileName;
///// <summary>
///// 通过构造方法将要下载的Url和要保存的文件名传进来
///// </summary>
///// <param name="url"></param>
///// <param name="fileName"></param>
//public DownloadUtil(string url,string fileName)
//{
// this.url = url;
// this.fileName = fileName;
//}
/// <summary>
/// 返回为byte数组,意味着用户
/// 可以不用提供文件名来下载。
/// 用户可以用得到的byte数组
/// 自行构造文件。
/// 这样一来,从外面传过来url
/// 和fileName的地方可以由构造
/// 转移到DownloadData中了。
/// </summary>
/// <returns></returns>
public byte[] DownloadData(string url,string fileName)
{
//不光WebResponse的获得使用异步方式
//连读取数据都使用异步方式。
//创建WebRequest对象
//WebRequest wr = WebRequest.Create("http://blog.sina.com.cn/dalishuishou");
this.fileName = fileName;
WebRequest wr = WebRequest.Create(url);
//开始异步地获取回应对象
//如果有了回应对象,那么把过程交给GetResponseCallBack去处理
wr.BeginGetResponse(new AsyncCallback(GetResponseCallBack), wr);
are.WaitOne();
return list.ToArray();
}
/// <summary>
/// 万一某个变态说:
/// 俺不要下载了就保存
/// 俺就要byte数组。
/// 哼哼,老子等着你呢。
/// </summary>
/// <param name="url"></param>
/// <returns></returns>
public byte[] DownloadData(string url)
{
return DownloadData(url, "");
}
/// <summary>
/// 当有回应对象时调用这个方法来处理。
/// </summary>
/// <param name="result"></param>
void GetResponseCallBack(IAsyncResult result)
{
//拿到那个请求对象
WebRequest wr = result.AsyncState as WebRequest;
//如果回应回完了,那么拿到回应对象
WebResponse wsp = wr.EndGetResponse(result);
//从回应中拿到流
Stream st = wsp.GetResponseStream();
//将异步操作过程中用到的信息封装为对象
DownloadInfo di = new DownloadInfo();
di.ReadSt = st;
//用文件名不为空来判断不填文件名的变态。
if (fileName!="")
{
//输出的文件流,此处也可替换为其他的流。
//FileStream fs = new FileStream("c:\\ee.txt", FileMode.Create, FileAccess.Write);
FileStream fs = new FileStream(fileName, FileMode.Create, FileAccess.Write);
di.WriteSt = fs;