Http实现断点下载和进度显示
一.背景
公司项目有一个需求,用户需要将较大的数据文件从服务器到本地,为了减少用户的等待时间,要实现文件的预下载功能,并且支持断点下载和进度显示,需求完成后简单记录一下实现过程。
二.断点下载
1.工具类
public class HttpUtils
{
/// <summary>
/// 下载文件,支持断点续传
/// </summary>
/// <param name="url"></param>
/// <param name="savePath"></param>
/// <param name="action"></param>
public static void DownloadFile(string url, string savePath, Action<double> action)
{
//如果存在下载文件则直接返回
if (File.Exists(savePath))
{
return;
}
//临时文件地址
var tempPath = savePath + ".temp";
var fs = new FileStream(tempPath, FileMode.OpenOrCreate, FileAccess.Write);
var request = (HttpWebRequest)HttpWebRequest.Create(url);
var response = (HttpWebResponse)request.GetResponse();
//文件总长度
var totalLength = response.ContentLength;
//临时文件长度
var currentLength = fs.Length;
//如果存在临时数据
if (currentLength > 0 && currentLength != totalLength)
{
request = (HttpWebRequest)HttpWebRequest.Create(url);
//请求添加起始范围
request.AddRange(fs.Length);
//设置文件指针位置
fs.Seek(fs.Length, SeekOrigin.Begin);
//断点续传
response = (HttpWebResponse)request.GetResponse();
}
if (response != null && currentLength != totalLength)
{
var buffer = new byte[1024];
using (Stream stream = response.GetResponseStream())
{
var size = 0;
while ((size = stream.Read(buffer, 0, buffer.Length)) > 0)
{
//写入文件
fs.Write(buffer, 0, size);
currentLength += size;
var percent = currentLength * 1.00 / totalLength;
//显示进度
action.Invoke(Math.Round(percent * 100, 2));
}
}
}
if (totalLength == currentLength)
{
fs.Close();
//重命名临时文件为目标文件
File.Move(tempPath, savePath);
}
}
}
2.代码使用
class Program
{
public static void Main(string[] args)
{
string url = "xxxxx";
string path = @"E:\临时\11111.zip";
HttpUtils.DownloadFile(url, path, c => Console.WriteLine($"{c}%"));
}
}