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

本文转载: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); //模拟慢速设备
    }
}

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏Golang语言社区

[Go 语言社区] Golang架构底层---日志函数

服务器后台架构,日志是必不可少的一个功能模块,日志可以分为很多中:统计日志,访问日志,错误日志等 今天大家发是运行中的日志函数 // 日志函数,传入数据为字...

3336
来自专栏智能大石头

XCode读取Excel数据(适用于任何数据库)

虽然是充血模型,虽然是强类型,XCode同样支持遍历任何数据库结构,并以强类型(相对于DataSet等字典访问)方式读取数据。 要遍历数据库结构是很容易的事情,...

2178
来自专栏逸鹏说道

EF批量操作数据与缓存扩展框架

在原生的EF框架中,针对批量数据操作的接口有限,EF扩展框架弥补了EF在批量操作时的接口,这些批量操作包括:批量修改、批量查询、批量删除和数据缓存,如果您想在E...

4216
来自专栏Golang语言社区

关于JSON.stringify和Unicode编码,需要注意的几点

1JSON.stringify会自动把所要转换内容中的汉字转换为Unicode编码 2浏览器间有差别,个别浏览器会把将要提交表单内容中的Unicode编码自动转...

3804
来自专栏蘑菇先生的技术笔记

c#实现redis客户端(一)

2846
来自专栏ASP.NET MVC5 后台权限管理系统

ASP.NET MVC5+EF6+EasyUI 后台管理系统(63)-Excel导入和导出-自定义表模导入

前言 上一节使用了LinqToExcel和CloseXML对Excel表进行导入和导出的简单操作,大家可以跳转到上一节查看: ASP.NET MVC5+EF...

4065
来自专栏木宛城主

SharePoint 创建 Lookup 类型的Site Column解决跨站问题

在某些情况下,我们需要去引用其他List中的数据,比如在网站集(Site Collection)上有个List叫Country,在其子网站(WebSite)有...

2399
来自专栏Golang语言社区

关于JSON.stringify和Unicode编码,需要注意的几点

1JSON.stringify会自动把所要转换内容中的汉字转换为Unicode编码 2浏览器间有差别,个别浏览器会把将要提交表单内容中的Unicode编码自动转...

3978
来自专栏Porschev[钟慰]的专栏

【2013年】开发常见问题回顾(一)

记录开发中遇到的和别人问的较多的问题.... IE10中LinkButton不可用     这应该是2013年初遇到的一个BUG,当使用Asp.Net开发Web...

2855
来自专栏王清培的专栏

Redis 数据结构与内存管理策略(下)

Redis 数据结构与内存管理策略(下) 标签: Redis Redis数据结构 Redis内存管理策略 Redis数据类型 Redis类型映射 作者:王清培...

3258

扫码关注云+社区

领取腾讯云代金券