httpClient大文件下载

在一直项目中使用文件下载,同事反应下载文件做进度条的时候没有正常显示进度条 大致代码如下
复制代码
public class DowmloadModel
{
    public string Url { get; set; }
    public string LocalSaveFullPath { get; set; }
    public bool Iscontinue { get; set; }
    public Action<double> ProgressRollBack { get; set; }

    public CancellationToken CancellationToken { get; set; }


}
public class DownloadHelper
{
    public static async Task DowmloadResumeFilel(DowmloadModel dowmloadModel)
    {
        try
        {
            //不建议使用WebResponse,所以这里用了未被淘汰的HttpClient
            var client = new HttpClient();
            //默认是下载新文件
            long downloaded = 0;
            if (dowmloadModel.Iscontinue)
            {
                if (File.Exists(dowmloadModel.LocalSaveFullPath))
                {
                    // 如果是续传,获取已经下载了多少
                    downloaded = new FileInfo(dowmloadModel.LocalSaveFullPath).Length;
                }
            }
            else
            {
                //不是续传,重新下载的就把原来的删了
                File.Delete(dowmloadModel.LocalSaveFullPath);
            }
            var request = new HttpRequestMessage(HttpMethod.Get, dowmloadModel.Url);
            //从指定位置开始下载文件,这样子写法兼容断点续传
            request.Headers.Range = new RangeHeaderValue(downloaded, null);
            using (var response = await client.SendAsync(request))
            {
                //检查请求是否成功,官方语法糖封装
                response.EnsureSuccessStatusCode();
                //记录总下载量
                var totalLength = response.Content.Headers.ContentRange.Length;
                using var stream = await response.Content.ReadAsStreamAsync();
                //启用文件追加模式,确保之前下载一半的文件还能被续上
                using var fileStream = new FileStream(dowmloadModel.LocalSaveFullPath, FileMode.Append, FileAccess.Write);
                //传输层的优化buffer大小一般在4KB左右,选择4KB可以与传输层匹配,减少 copying数据的次数, 提高效率
                var buffer = new byte[4096];
                int read = 0;
                //缓存已下载的字节数量,到达一个阈值再通知界面变更
                var temp = 0;
                while ((read = await stream.ReadAsync(buffer)) > 0)
                {
                    //如果外部取消了就不继续下载了
                    dowmloadModel.CancellationToken.ThrowIfCancellationRequested();
                    //将字节数追加写入文件
                    await fileStream.WriteAsync(buffer.AsMemory(0, read));
                    downloaded += read;
                    temp += read;
                    //以百分之一进度为阈值更新界面
                    if (temp > totalLength / 100)
                    {
                        dowmloadModel.ProgressRollBack((double)((double)downloaded / totalLength) * 100);
                        temp = 0;
                    }
                }
            }
        }
        catch (Exception ex)
        {
            //Log.Error($"下载出错:{ex}");
        }
    }
}
复制代码

UI显示部分

复制代码
await DownloadResumeFile(new DownloadModel()
{
    Url = dataContext.ApkFilePath,
    Iscontinue = false,
    LocalSaveFullPath = Path.Combine(Path.GetTempPath(), $"{dataContext.AppName}.apk"),
    ProgressRollBack = rusult =>
   {
      dataContext.DownloadProgress = rusult;
   },
     CancellationToken = dataContext.DownloadingCancellationToken.Token,
});
复制代码

分析之后定位在

using (var response = await client.SendAsync(request))  和 dataContext.DownloadProgress = rusult;
最后修改为 using (var response = await client.SendAsync(request,HttpCompletionOption.ResponseHeadersRead))

Application.Current.Dispatcher.Invoke(() =>
{
  dataContext.DownloadProgress = rusult;
});

修复正常。做下记录。



posted @   stweily  阅读(29)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· DeepSeek 开源周回顾「GitHub 热点速览」
· 记一次.NET内存居高不下排查解决与启示
· 物流快递公司核心技术能力-地址解析分单基础技术分享
· .NET 10首个预览版发布:重大改进与新特性概览!
· .NET10 - 预览版1新功能体验(一)
点击右上角即可分享
微信分享提示