首页 > 编程语言 >C#如何使用HttpClient对大文件进行断点上传和下载

C#如何使用HttpClient对大文件进行断点上传和下载

时间:2024-06-23 23:20:47浏览次数:26  
标签:文件 Http 请求 C# 上传 对大 断点 下载

什么是Http的断点上传和下载

断点上传:在向服务商上传大文件的时候,将一个大的文件拆分成多个小的文件,每个文件通过单独的Http请求上传给服务器。

断点下载:在向服务器请求下载一个大的资源文件的时候,不是一次Http请求返回所有的资源文件内容。而是先通过Head请求,拿到资源文件的大小(单位:字节)。然后每次请求只请求一部分字节的数据,将请求到的数据在本地进行拼接。

断点上传和下载的优点

1、避免网络中断时,重传所有资源文件内容。

2、提高服务器并发,防止单个客户端长时间和服务器保持连接。

3、可以实时显示上传和下载的进度。

断点上传和下载的缺点

1、占用更多的网络带宽,因为每次Http请求都会附带各种额外的信息。

2、上传和下载的时间会变得长一点,因为是通过多次请求来完成断点上传和下载。

实现基本原理

依赖Http协议的几个基本的协议头来完成断点上传和下载。

1、Content-Range:这是一个响应头,表示请求的资源文件大小,我们可以通过Head请求拿到的资源文件的字节数,就是读取的这个字段。

2、Range :这是一个请求头,表示客户端要请求的数组的范围。如如:"0-1000"、"1001-2000"、"2001-3000"等,服务器接收到这个请求头之后,只给我们返回对应范围内的资源字节数组,不会把所有的字节数都返回给我们。

一般请求下,这两个请求头就可以实现简单的断点上传和下载。本篇文章我们使用一个WPF项目演示断点下载。

string url = "http://file.cshelloworld.com/images/1771477326069108736.jpg";
long totalSize = 0;//文件总大小
long downLoadingSize = 0;//当前已经下载了多少

private void Button_Click(object sender, RoutedEventArgs e)
{
    Task.Run(async () =>
    {
        //获取到文件总大小 通过head请求
        using HttpClient client = new HttpClient();
        HttpRequestMessage requestMessage = new HttpRequestMessage(HttpMethod.Head, url);
        var response = await client.SendAsync(requestMessage);
        totalSize = response.Content.Headers.ContentLength.Value;
        using FileStream fileStream = new FileStream("d:\\a.jpj", FileMode.Create, FileAccess.Write, FileShare.Read);

        //开始分片下载
        while (downLoadingSize < totalSize)
        {
            //组装range 0,1000 1000,2000 0,9999
            long start = downLoadingSize;
            long end = start + 1000;
            if (end > (totalSize - 1))
            {
                end = totalSize - 1;
            }
            client.DefaultRequestHeaders.Range = new System.Net.Http.Headers.RangeHeaderValue(start, end);
            var res = await client.GetAsync(url);
            byte[] bytes = await res.Content.ReadAsByteArrayAsync();
            await fileStream.WriteAsync(bytes, 0, bytes.Length);
            //更新UI的进度
            downLoadingSize += bytes.Length;
            int process = (int)((downLoadingSize / (decimal)totalSize) * 100);
            this.Dispatcher.Invoke(() =>
            {
                cont.Text = process + "%";
                this.processBar.Value = process;
            });
        }
        fileStream.Close();
    });
}

在以上代码中,首先是Head请求获取资源文件大小。

我们主要通过以下代码实现,通过设置HttpMethod.Head构建一个HttpRequestMessage的请求对象

HttpRequestMessage requestMessage = new HttpRequestMessage(HttpMethod.Head, url);

其次是断点下载过程中,Range请求头如何设置:

client.DefaultRequestHeaders.Range = new System.Net.Http.Headers.RangeHeaderValue(start, end);

每次请求到字节数组之后,我们将字节数组写入到本地的文件流中,如果网络断开,下次请求的时候,读取本地文件大小,假设本地未见大小为1000,那么我们请求的时候Range就从1001开始,这样服务器就给我们返回的是1001之后的字节数组了。

当然在这个过程中,我们还要考虑一个问题,如果服务器的资源文件发生了修改会怎么样。如果我们继续下载的话 ,就会出现问题。因为客户端下载的文件都不是同一个文件。这种情况下,我们可以使用Http的请求头Last-Modified来判断文件是否修改,这个请求头表示文件的最近一次修改时间。当我们第一次请求数据的时候可以把这个请求头的时间记录下来,后续请求如果服务器资源文件发生变化,我们就将本地文件全部删除,然后重新发起请求。

联系站长

站长公众号

推荐阅读

标签:文件,Http,请求,C#,上传,对大,断点,下载
From: https://www.cnblogs.com/caoruipeng/p/18264122

相关文章

  • C++系统相关操作4 - 获取CPU(指令集)架构类型
    1.关键词2.sysutil.h3.sysutil.cpp4.测试代码5.运行结果6.源码地址1.关键词关键词:C++系统调用CPU架构指令集跨平台实现原理:Unix-like系统:可以通过uname-m命令获取CPU架构类型。Windows系统:可以通过环境变量PROCESSOR_ARCHITECTURE获取CPU......
  • [GodotDL C# D2]从空格控制转弯到撞墙检测
    书接上回:https://www.cnblogs.com/meny233/p/18250399新增功能:空格控制转弯导出变量撞墙检测音乐播放前戏点击查看代码usingGodot;usingSystem;publicpartialclassLine:CharacterBody3D{ [Export] publicfloatSpeed=10f; [Export] publicboolturn......
  • ABC359E的有趣解法
    题意:给定一个h序列,对于\(h_i\),找到一个\(j\)满足\(j<i\)且\(h_j>=h_i\),令\(ans_i=h_i*(i-j+1)+ans_j+1\),最后输出ans序列。赛时给了个很魔怔的解法,不知道是不是正解,反正是过了(摊手)我们可以开一个idx数组,将h[i]从小到大排序后将其原下表存入idx数组,这样我们从前......
  • LeetCode热题100(136.只出现一次数字)
    一.只出现一次数字给你一个非空整数数组nums,除了某个元素只出现一次以外,其余每个元素均出现两次。找出那个只出现了一次的元素。你必须设计并实现线性时间复杂度的算法来解决此问题,且该算法只使用常量额外空间。示例1:输入:nums=[2,2,1]输出:1示例2:输入:nums=......
  • 王鼎杯 RCE命令執行 五字節限制
    源碼:<?phperror_reporting(0);highlight_file(__FILE__);if(strlen($_GET['cmd'])<=5&&!preg_match('/rm/',$_GET['cmd'])){echoshell_exec($_GET['cmd']);}?>对cmd限制长度五字节起初是想通过变量来绕过五字节但好像不起作用......
  • C++系统相关操作3 - 获取操作系统的平台类型
    1.关键词2.sysutil.h3.sysutil.cpp4.测试代码5.运行结果6.源码地址1.关键词C++系统调用操作系统平台类型跨平台2.sysutil.h#pragmaonce#include<cstdint>#include<string>namespacecutl{/***@briefOperatingsystemplatformtype.......
  • LeetCode 70. 爬楼梯 使用c++解答
    假设你正在爬楼梯。需要 n 阶你才能到达楼顶。每次你可以爬 1 或 2 个台阶。你有多少种不同的方法可以爬到楼顶呢?示例1:输入:n=2输出:2解释:有两种方法可以爬到楼顶。1.1阶+1阶2.2阶示例2:输入:n=3输出:3解释:有三种方法可以爬到楼顶。1.1阶+1阶......
  • opencv
    importtimeimportcv2importpyautoguidefget_xy(img_model_path):"""用来判定游戏画面的点击坐标:paramimg_model_path:用来检测的模板图片的路径:return:以元组形式返回检测到的区域的中心坐标"""#将屏幕截图保存pyautogui.scr......
  • C - Tile Distance 2
    C-TileDistance2https://atcoder.jp/contests/abc359/tasks/abc359_c 思路在x方向上,让s<t然后如果s在tile的左边,移动到右边, 如果t在tile的右边,移动到左边,计算x和y方便的必走的steps,y方向上容易计算(跨的格子就是),x方向有些复杂,s在x方向上,不用花费(配合y方向上走步......
  • AI 大模型企业应用实战(10)-LLMs和Chat Models
    1模型来看两种不同类型的模型--LLM和聊天模型。然后,它将介绍如何使用提示模板来格式化这些模型的输入,以及如何使用输出解析器来处理输出。LangChain中的语言模型有两种类型:1.1ChatModels聊天模型通常由LLM支持,但专门针对会话进行了调整。提供者API使用与纯文本补全模......