现在网上很多的网络下载使用的都是 WebResponse,使用的时候微软也会告诉我们这玩意已经过时了,推荐我们使用 HttpClient,但是网上少有这个库的轮子,所以现在我们来造一个:
本文仅仅介绍核心用法,以及部分业务,具体业务可以自行添加
var httpClient= new HttpClient();// 如果是续传,获取已经下载了多少
var downloadProgress= new FileInfo(文件存放地址).Length;
tips:这里获得已经下载文件的大小,为后面的续传做准备
var request = new HttpRequestMessage(HttpMethod.Get, 下载的URL链接);//从指定位置开始下载文件,这样子可以实现断点续传
request.Headers.Range = new RangeHeaderValue(downloadProgress, null);
这样子就可以实现从指定大小位置去下载,完成断点续传。
using (var response = await client.SendAsync(request))
{//检查请求是否成功,官方语法糖封装response.EnsureSuccessStatusCode();//这个是总下载量,也就是URL的东西一共有多大var totalLength = response.Content.Headers.ContentRange.Length;using var stream = await response.Content.ReadAsStreamAsync();//启用文件追加模式,确保之前下载一半的文件还能被续上using var fileStream = new FileStream(文件存放地址, FileMode.Append,FileAccess.Write);//传输层的优化buffer大小一般在4KB左右,选择4KB可以与传输层匹配,减少copying数据的次数,提高效率var buffer = new byte[4096];int read;//缓存已下载的字节数量,到达一个阈值再通知界面变更,根据业务随便变更var temp = 0;//每次读取一个buffer的量,处理逻辑,写入文件while ((read = await stream.ReadAsync(buffer)) > 0){//外部传入的CancellationToken,用于随时取消下载任务XXX.CancellationToken.ThrowIfCancellationRequested();//将字节数追加写入文件await fileStream.WriteAsync(buffer.AsMemory(0, read));downloaded += read;temp += read;//这里以例子以百分之一进度为阈值更新界面,也可以全部通知出去,不沾染业务if (temp > totalLength / 100){//这里触发需要触发的回调函数回调((double)((double)downloadProgress/ totalLength) * 100);temp = 0;}}
}
部分地方填入自己的代码,可以实现取消,暂停,续传等功能
由于该方法需要外界传入的参数比较多,>=5个(lindexi推荐参数(•̀ᴗ•́)و),所以建议封装成一个类 ,下面给出Demo仅供参考
public class DownloadModel
{/// <summary>/// 需要下载的URL路径/// </summary>public string Url { get; set; }/// <summary>/// 文件下载后保存的路径/// </summary>public string LocalSaveFullPath { get; set; }/// <summary>/// 是否是续点下载/// </summary>public bool Iscontinue { get; set; }/// <summary>/// 进度条回报方法/// </summary>public Action<double> ProgressRollBack { get; set; }/// <summary>/// 取消/// </summary>public CancellationToken CancellationToken { get; set; }
}
这样一个基于HttpClient支持续传的网络下载就OK了