ASP.NET用HttpListener实现文件断点续传

简介: 本文转载:http://www.cnblogs.com/TianFang/archive/2007/01/03/610739.html 断点续传的原理很简单,就是在Http的请求和应答的报文头上和一般的下载有所不同而已。

本文转载:http://www.cnblogs.com/TianFang/archive/2007/01/03/610739.html

断点续传的原理很简单,就是在Http的请求和应答的报文头上和一般的下载有所不同而已。

普通方式请求服务器上的一个文时,所发出的请求和接受到的服务器如下:

request header:
Cache-Control: no-cache
Connection: close
Pragma: no-cache
Accept: */*
Host: localhost

response header:
200
Content-Type: application/octet-stream
Content-Disposition: attachment;FileName=time.pdf

当服务器支持断点续传时,请求和应答如下:

request header:
Cache-Control: no-cache
Connection: close
Pragma: no-cache
Accept: */*
Host: localhost
Range: bytes=15360-

response header:
206
Content-Type: application/octet-stream
Content-Disposition: attachment;FileName=time.pdf

两个报文的不同部分已用红色部分标记出来。可以看出:

客户端报文头中通过Range报文头来标识客户期望的下载位置。
服务器的应答号为200时表示是从文件头开始下载,而206表示是从文件的特定位置开始传输,客户端从该应答号可以看出服务器是否支持断点续传。
也就是说,支持断点续传的时候可以从文件任一部分开始下载,而普通的方式只能从文件头开始下载。

要使得服务器支持断点续传,需要解决以下几个问题:

1。需要判断客户端是否是续传请求,如果是续传请求时,需要获取客户端所需的文件范围。

从上面的分析可以看到,当客户端为断点传输时,报文头里会增加Range字段,则可以通过如下方式判断是否是断点传输请求。

string range = request.Headers["Range"];
bool isResume = string.IsNullOrEmpty(range);

2。对客户端做正确的应答相应,以通知客户端服务器支持端点续传

当为断点传输请求时,对客户端的相应号可以通过如下方式设置:

response.StatusCode = 206;

3。传送客户端所需正确的内容

传送客户端所需正确的内容一般需要经过以下几个步骤

通过分析range来获取客户端的文件请求范围。
断点传输请求时,所需的长度比文件的长度短,故需要正确的设置response.ContentLength64属性。
正确传输所需的内容
代码示例:

static void ProcessHttpClient(object obj)
{
    HttpListenerContext context = obj as HttpListenerContext;
    HttpListenerRequest request = context.Request;
    HttpListenerResponse response = context.Response;

    FileStream fs = File.OpenRead(@"f:\123.pdf"); //待下载的文件

    long startPos = 0;
    string range = request.Headers["Range"];
    bool isResume = string.IsNullOrEmpty(range);
    if (isResume) //断点续传请求
    {
        //格式bytes=9216-
        startPos = long.Parse(range.Split('=')[1].Split('-')[0]);
        response.StatusCode = 206;
        response.ContentLength64 = fs.Length - startPos;
        fs.Position = startPos; //设置传送的起始位置
    }
    else
    {
        response.ContentLength64 = fs.Length;
    }

    Console.WriteLine("request header");
    Console.WriteLine(request.Headers.ToString());

    response.ContentType = "application/octet-stream";

    string fileName = "time.pdf";
    response.AddHeader("Content-Disposition", "attachment;FileName=" + fileName);
    Stream output = response.OutputStream;

    try
    {
        Console.WriteLine("response header");
        Console.WriteLine(response.Headers.ToString());
        CopyStream(fs, output); //文件传输
        output.Close();
    }
    catch (HttpListenerException e) //在未写完所有文件时,如果客户端关闭连接,会抛此异常
    {
        Console.WriteLine(e.Message);
        //output.Close(); //如果执行此函数会抛异常在写入所有字节之前不能关闭流。
    }
}

static void CopyStream(Stream orgStream, Stream desStream)
{
    byte[] buffer = new byte[1024];

    int read = 0;
    while ((read = orgStream.Read(buffer, 0, 1024)) > 0)
    {
        desStream.Write(buffer, 0, read);

        System.Threading.Thread.Sleep(1000); //模拟慢速设备
    }
}

  

目录
相关文章
|
2月前
|
C# Windows
.NET开源免费的Windows快速文件搜索和应用程序启动器
今天大姚给大家分享一款.NET开源(MIT License)、免费、功能强大的Windows快速文件搜索和应用程序启动器:Flow Launcher。
|
6天前
|
算法 API 数据安全/隐私保护
.NET使用原生方法实现文件压缩和解压
.NET使用原生方法实现文件压缩和解压
.NET使用原生方法实现文件压缩和解压
|
6天前
|
存储 C#
.NET使用CsvHelper快速读取和写入CSV文件
.NET使用CsvHelper快速读取和写入CSV文件
|
1月前
|
存储 安全 Unix
【.Net Core】深入理解IO之文件和目录
【.Net Core】深入理解IO之文件和目录
33 4
|
16天前
|
存储 C#
.NET使用CsvHelper快速读取和写入CSV文件
优秀项目和框架精选 该项目已收录到C#/.NET/.NET Core优秀项目和框架精选中,关注优秀项目和框架精选能让你及时了解C#、.NET和.NET Core领域的最新动态和最佳实践,提高开发工作效率和质量。坑已挖,欢迎大家踊跃提交PR推荐或自荐(让优秀的项目和框架不被埋没🤞)。
|
1月前
|
开发框架 .NET Linux
【.NET Developer】已发布好的.NET Core项目文件如何打包为Docker镜像文件
该文介绍了如何不使用VS2019手动创建ASP.NET Core Blazor项目的Dockerfile并构建Docker镜像。首先,创建名为Dockerfile的文件,并复制提供的Dockerfile内容,该文件指定了基础镜像和工作目录。然后,通过CMD在项目目录下运行`docker build -t 自定义镜像名 .`来生成镜像。最后,使用`docker run`命令启动容器并验证项目运行。此外,文章还提到了将镜像推送到Azure Container Registry (ACR)的步骤。
|
9月前
|
对象存储
.net core 阿里云接口之拷贝文件
紧接上文, 1)[.net core 阿里云接口之获取临时访问凭证](https://developer.aliyun.com/article/1363447?spm=a2c6h.12873639.article-detail.7.2b0e5b1cpeWbZ5 ".net core 阿里云接口之获取临时访问凭证") 2)[.net core 阿里云接口之将指定的OSS文件下载到流](https://developer.aliyun.com/article/1363886 ".net core 阿里云接口之将指定的OSS文件下载到流") 本文继续阿里云接口调用,将指定的OSS文件下载到流。
43 0
|
9月前
|
C#
.net core 从(本地)服务器获取APK文件并解析APK信息
## 1、apk解析除了使用客户端利用aapt.exe、unzip.exe开发客户端解析外,还可以直接利用服务进行解析 ```csharp /// <summary> /// 从本地服务器获取APK文件并解析APK信息 /// </summary> /// <param name="fileName">APK文件的完整路径</param> /// <returns></returns> [HttpPost, HttpGet, HttpOptions, CorsOptions] public IActionResult DecodeAPK(string fileName) { if(fi
54 0
|
9月前
|
JavaScript 前端开发 关系型数据库
.net core + vue + elementui 删除指定日期段、指定路径下的所有文件
# 1、呈现效果 ![image.png](https://ucc.alicdn.com/pic/developer-ecology/j2ygdazy447va_0782583bbc894c33a079db9e44385acd.png) # 2、后端 ## 1)服务层 ```csharp /// <summary> /// 删除指定修改日期段及指定路径下的所有文件 /// </summary> /// <param name="filepath">指定路径</param> /// <returns>返回删除结果提示</returns> public string DeleteSpecif
53 0
|
9月前
|
C#
.net core 删除指定路径下的所有文件以及文件夹(文件夹建议保留目录)
1、服务层 ```csharp /// <summary> /// 删除指定路径下的所有文件 /// </summary> /// <param name="filepath">指定路径</param> /// <returns></returns> public string DeleteSpecifiedPathAllFile(string filepath) { try { DirectoryInfo info = new DirectoryInfo(filepath); // 去除文件夹的只读属性 info.Attribu
79 0