• 设为首页
  • 点击收藏
  • 手机版
    手机扫一扫访问
    迪恩网络手机版
  • 关注官方公众号
    微信扫一扫关注
    公众号

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

原作者: [db:作者] 来自: [db:来源] 收藏 邀请

本文转载: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人参与评论

请发表评论

全部评论

专题导读
热门推荐
热门话题
阅读排行榜

扫描微信二维码

查看手机版网站

随时了解更新最新资讯

139-2527-9053

在线客服(服务时间 9:00~18:00)

在线QQ客服
地址:深圳市南山区西丽大学城创智工业园
电邮:jeky_zhao#qq.com
移动电话:139-2527-9053

Powered by 互联科技 X3.4© 2001-2213 极客世界.|Sitemap