首页 > 其他分享 >httpClient大文件下载

httpClient大文件下载

时间:2024-12-17 16:10:01浏览次数:3  
标签:文件 await dowmloadModel var new public 下载 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;
});

修复正常。做下记录。



标签:文件,await,dowmloadModel,var,new,public,下载,httpClient
From: https://www.cnblogs.com/stweily/p/18612731

相关文章

  • 实验6 模板类、文件I/O和异常处理
    实验任务4代码Vector.hpp1#pragmaonce2#include<iostream>3#include<stdexcept>45template<typenameT>6classVector{7public:8//构造函数9Vector(intsize);10Vector(intsize,Tvalue);11Vector(constV......
  • webbroker从本地HTML文件导入
    a01.rarprocedureTWebModule1.WebModule1DefaultHandlerAction(Sender:TObject;Request:TWebRequest;Response:TWebResponse;varHandled:Boolean);varFileContent:TStringList;beginFileContent:=TStringList.Create;//假设你的HTML文件位于Web......
  • 好,我们以你的 `euclidolap.proto` 文件为例,调整代码结构,让服务逻辑更清晰,同时将 `eucl
    好,我们以你的euclidolap.proto文件为例,调整代码结构,让服务逻辑更清晰,同时将euclidolap模块分离到独立文件中。假设文件结构调整我们将euclidolap.proto生成的代码放到src/euclidolap模块中,同时将服务端逻辑分开组织。最终文件结构如下:project/├──build.rs......
  • 分布式文件系统HDFS
    HDFS简介HDFS(HadoopDistributedFileSystem)是一个分布式文件系统,是Hadoop生态系统的核心组件之一。它被设计用来在廉价的硬件设备上存储大规模的数据,并且能够提供高容错性和高吞吐量的数据访问。例如,在一个大型的互联网公司,每天会产生海量的用户行为数据,如浏览记录、购买记......
  • 实验6 模板类、文件I/O和异常处理
    1.实验任务4Vector.hpp源代码:点击查看代码#pragmaonce#include<iostream>#include<stdexcept>#include<algorithm>//forstd::copytemplate<typenameT>classVector{private:T*data;size_tsize;public://构造函数Vecto......
  • 天虎程序Phone APP下载设置定位失败怎么解决
    天虎程序Phone的APP拨号软件怎么下载呢?首先用浏览器扫描二维码,点击下载,然后按照提示安装就可以,这个非常简单。下载后,点击软件界面按####加拨号连接蓝牙,蓝牙连接好后就可以正常使用了。请联系图片上电话或微心2081003456索取下载phone程序APP定位失败更换APP即可。1:打开APP......
  • mfc140.dll文件缺失的修复方法分享,全面分析mfc140.dll的几种解决方法
    mfc140.dll是MicrosoftFoundationClasses(MFC)库中的一个动态链接库(DLL)文件,它是微软基础类库的一部分,为Windows应用程序的开发提供了丰富的类库和接口。MFC库旨在简化Windows应用程序的开发过程,提供了一系列预定义的C++类,这些类封装了WindowsAPI函数,使得开发者可以更方便地创......
  • Keil uVision5生成bin文件
    使用KeiluVision5将程序代码生成bin格式文件的方法1.点击魔术棒(OptionsforTarget...)2.选择User界面,勾选上AfterBuild、Rebuild的Run#1在UserCommand中填入下面的指令。fromelf--bin-o"$L@L.bin""#L"......
  • msvcp100.dll文件缺失的修复方法分享,全面分析msvcp100.dll的修复方法
    msvcp100.dll是一个动态链接库(DLL)文件,属于MicrosoftVisualC++2010RedistributablePackage的一部分。这个文件对于运行使用MicrosoftVisualC++2010编译器编译的应用程序至关重要。msvcp100.dll包含了C++标准库的实现,提供了应用程序运行时所需的核心功能,如输入/......
  • 实验6 模板类、文件I/O和异常处理
    task4源码:1#include<iostream>2#include<stdexcept>3#include<algorithm>45template<typenameT>6classVector{7private:8T*data;9size_tsize;//无符号整数类型1011public:12Vector(in......