WebClient是一个功能强大的类,通过直接使用或继承它可以很容易的下载各种Http和Ftp资源。在客户端程序中,我一般使用的是同步下载的方式来下载文件,然而WebClient的同步下载方法稍微薄弱了些,使得其在下载大文件方面存在很大的不足,主要体现在如下方面:
-
下载的时候无法取消
-
无法获取到下载速度
其实要实现这两方面的控制主要是要实现对ResponseStream的控制即可,然而,WebClient没有从一个统一的入口来获取ResponseStream,并不能通过简单的继承WebClient来实现该功能,因此,还需要对WebRequest进行封装,在WebRequest中返回封装的Stream,通过新的Stream实现对下载的控制(稍微修改一下也可以支持异步的)。基本形式如下:
class WebClientPlus:WebClient
{
protected override WebResponse GetWebResponse(WebRequest request)
{
return base.GetWebResponse(request);
}
}
class WebRepuestPlus:WebRequest
{
WebRequest request;
public WebRepuestPlus(WebRequest request)
{
this.request = request;
}
public override System.IO.Stream GetRequestStream()
{
return base.GetRequestStream();
}
}
class WebStreamPlus:System.IO.Stream
{
System.IO.Stream stream;
public WebStreamPlus(System.IO.Stream stream)
{
this.stream = stream;
}
public override int Read(byte[] buffer, int offset, int count)
{
//这里可以实现速度的计算
return stream.Read(buffer, offset, count);
}
}
这样做后,可以通过修改代码,在WebClientPlus中保留对的WebStreamPlus引用,同时增强WebStreamPlus的功能,实现下载速度的计算(关闭直接调用其Close方法即可)。这样,就可以很容易实现我们所需要的功能了。
这种思路其实还是比较简单,就是要实现两个代理类:WebStreamPlus和WebRepuestPlus。这种代理类实现简单,写起来却较麻烦,如果用代码生成器来生成比较合适(目前还没有这种代码生成器,其实用反射写这种代码生成器应该不难)。(上面的代码只是一个示意,并没有写完)
按照这种思路,实现上传时候的控制也是很简单的。同样,也可以很容易扩展Webclient的功能,如对下载文件在内存中进行缓存、自动多次重连、断点续传等常用的下载功能。