C#编程总结(十二)断点续传

Posted on 2014-02-16 10:56 停留的风 阅读(384) 评论(3) 编辑 收藏

C#编程总结(十二)断点续传

我们经常使用下载工具,如bit精灵、迅雷、FlashGet,这些软件都支持断点续传。

断点续传即下载任务暂停后可以继续,而无需重新下载,即下载时需要通知服务器的起始位置。如果允许多线程进行分片下载,必须提供起始-截止位置。说到底就是可以选择下载某个片段,整个文件的字节流,可以截取流的片段,也能实现流的累积,最终完成文件下载。

一、原理

在 HTTP/1.1里新增的一个头属性:Range,也是现在众多号称多线程下载工具(如 FlashGet、迅雷等)实现多线程下载的核心所在。老版本的HTTP协议不支持,所以一些老的服务器还不支持断点续传。

Range(请求参数)

用于请求头中,指定第一个字节的位置和最后一个字节的位置,一般格式:

Range:(unit=first byte pos)-[last byte pos]

例如:Range:100-199,取文件流的100至199之间的字节。

Range:100,取位置为100后的所有字节。如果range 为正值,服务器应该开始发送从指定的 range 参数到 HTTP 实体中数据的末尾之间的数据。

Range:-99,取开始的100个字节。如果range 为负值,服务器应该开始发送从 HTTP 实体中数据的开头到指定的 range 参数之间的数据。

Content-Range (响应参数)

用于响应头,指定整个实体中的一部分的插入位置,他也指示了整个实体的长度。在服务器向客户返回一个部分响应,它必须描述响应覆盖的范围和整个实体长度。

一般格式:   

Content-Range: bytes (unit first byte pos) - [last byte pos]/[entity legth] 

例如:Content-Range: bytes 1024000-1126399/7421120

HTTP协议:http://www.w3.org/Protocols/rfc2616/rfc2616.html

二、C#中实现

在C#中使用AddRange方法向请求添加指定范围的字节范围标头

System.Net.HttpWebRequest

所有的方法:

常用的方法为例:

void AddRange(long from, long to);
指定范围起始、终止位置,来请求该片段的数据。
        // 摘要:
// 向请求添加指定范围的字节范围标头。
//
// 参数:
// from:
// 开始发送数据的位置。
//
// to:
// 停止发送数据的位置。
public void AddRange(long from, long to);

我们通过该方法,基于HTTP协议实现了断点续传,支持暂停、继续下载功能,为了更清晰显示效果,提供了进度条显示。效果图:

Request

请求的Range参数,我们可以清晰看到起具体值,这就是请求的片段。在这里可以清晰的看到HTTP协议版本、请求方法、请求地址等信息

Response

服务器根据请求的Range参数,只返回该片段的数据。我们可以清晰看到Content-Range的具体值。

注意:返回的StatusCode变为了PartialContent,说明是部分数据。

代码 含义
200 OK     请求成功返回
206 Partial Content     部分数据

 下载的核心代码:

        /// <summary>
/// 下载
/// </summary>
public void Download()
{
//从0计数,需要减一
long from = this.currentSize;
if (from < 0)
{
from = 0;
} long to = this.currentSize + this.step - 1;
if (to >= this.totalSize && this.totalSize > 0)
{
to = this.totalSize - 1;
}
this.Download(from, to);
}
/// <summary>
/// 下载
/// </summary>
/// <param name="url"></param>
/// <param name="range"></param>
public void Download(long from,long to)
{
if (this.totalSize == 0)
{
GetTotalSize();
}
if (from >= this.totalSize || this.currentSize >= this.totalSize)
{
this.isFinished = true;
return;
} HttpWebRequest request = (HttpWebRequest)HttpWebRequest.Create(url);
//request.Method = "GET";
request.AddRange("bytes", from, to); HttpWebResponse response = (HttpWebResponse)request.GetResponse();
string result = string.Empty;
if (response != null)
{
byte[] buffer = this.Buffer;
using (Stream stream = response.GetResponseStream())
{
int readTotalSize = 0;
int size = stream.Read(buffer, 0, buffer.Length);
while (size > 0)
{
//只将读出的字节写入文件
fs.Write(buffer, 0, size);
readTotalSize += size;
size = stream.Read(buffer, 0, buffer.Length);
} //更新当前进度
this.currentSize += readTotalSize; //如果返回的response头中Content-Range值为空,说明服务器不支持Range属性,不支持断点续传,返回的是所有数据
if (response.Headers["Content-Range"] == null)
{
this.isFinished = true;
}
}
}
}

项目源码:

http://files.cnblogs.com/yank/DownloadSample.rar

三、多线程下载

上述例子提供了简单的断点续传功能,如果想再进一步实现多线程下载。原理很简单,我们只需根据所要下载的文件大小,进行分块,没块启动一个线程进行下载,线程只负责下载自己负责的片段,一定要严格设置Range的值。具体实现这里不再介绍,如有兴趣,下来可以继续研究。

提醒一下:多线程下载的字节流如何保存为文件,是否必须按照先后顺序?

C#编程断点续传的更多相关文章

  1. Android Tips – 填坑手册

    出于: androidChina   http://www.androidchina.net/3595.html 学习 Android 至今,大大小小的坑没少踩,庆幸的是,在强大的搜索引擎与无私奉献的 ...

  2. android 开发从入门到精通

    Android-Tips This is an awesome list of tips for android. If you are a beginner, this list will be t ...

  3. ot

    https://blog.csdn.net/notice520/article/details/8135600 | android中的跨进程通信的实现(一)——远程调用过程和aidl - CSDN博客 ...

  4. C#编程总结(十二)断点续传

    C#编程总结(十二)断点续传 我们经常使用下载工具,如bit精灵.迅雷.FlashGet,这些软件都支持断点续传. 断点续传即下载任务暂停后可以继续,而无需重新下载,即下载时需要通知服务器的起始位置. ...

  5. iOS开发之网络编程--4、NSURLSessionDataTask实现文件下载(离线断点续传下载) <进度值显示优化>

    前言:根据前篇<iOS开发之网络编程--2.NSURLSessionDownloadTask文件下载>或者<iOS开发之网络编程--3.NSURLSessionDataTask实现文 ...

  6. iOS开发之网络编程--3、NSURLSessionDataTask实现文件下载(离线断点续传下载)

    前言:使用NSURLSessionDownloadTask满足不这个需要离线断点续传的下载需求,所以这里就需要使用NSURLSessionDataTask的代理方法来处理下载大文件,并且实现离线断点续 ...

  7. iOS开发之网络编程--使用NSURLConnection实现大文件断点续传下载+使用输出流代替文件句柄

    前言:本篇讲解,在前篇iOS开发之网络编程--使用NSURLConnection实现大文件断点续传下载的基础上,使用输出流代替文件句柄实现大文件断点续传.    在实际开发中,输入输出流用的比较少,但 ...

  8. iOS开发网络编程之断点续传-NSURLConnection

    最近在做一个小项目的时候,发现使用NSURLSession或者AFNNetworking进行断点续传时诸多的不便,于是自己封装了一个类来实现断点续传,在程序重新启动时仍然可以继续下载(需自己调用方法) ...

  9. Python学习笔记【第十五篇】:Python网络编程三ftp案例练习--断点续传

    开发一个支持多用户在线的FTP程序-------------------主要是学习思路 实现功能点 1:用户登陆验证(用户名.密码) 2:实现多用户登陆 3:实现简单的cmd命令操作 4:文件的上传( ...

随机推荐

  1. printf交替使用

    今天附带printf一些替代实现. 转载请注明出处:http://blog.csdn.net/u010484477谢谢^_^ 我们总是用printf做各种输出语句: printf("%d&q ...

  2. C# Windows Schedule task此次收购task下一步执行时间

    最近进行了一次需求和Windows Schedule task相关职能,通过schedule,计算下一次运行task时间. 它用于由第三方DLL实现,以下网站,以下载来自: http://tasksc ...

  3. httpclient总结

    1.httpclient总结:一.基本知识准备(1)构建URI工具类,URIBuilder(2)HttpResponse类,可以添加Header信息 获取所有Header信息的方法,调用HeaderI ...

  4. ASP.NET MVC+EF框架+EasyUI实现权限管理系列(14)-主框架搭建

    原文:ASP.NET MVC+EF框架+EasyUI实现权限管理系列(14)-主框架搭建    ASP.NET MVC+EF框架+EasyUI实现权限管系列 (开篇)   (1):框架搭建    (2 ...

  5. 从头学起android&lt;GridView网格视图.二十八.&gt;

    GridView基于组件的网络格所有的形式的组分的,例如:当制作专辑,所有的图片将在相同的尺寸在不同的显示格在孩子,是否能够依靠这个组件完成.此组件的继承结构参见例如下面: java.lang.Obj ...

  6. AJAX及其跨域的主要解决方法

    AJAX = Asynchronous JavaScript andXML(异步的 JavaScript 和 XML).通过在后台与服务器进行少量数据交换,使网页实现异步更新.要明白异步交互可以通过同 ...

  7. linux-ubuntu关闭防火墙

    SYNOPSIS iptables [-t table] {-A|-C|-D} chain rule-specification ip6tables [-t table] {-A|-C|-D} cha ...

  8. Swift-开发 # 1.2版本迁移

    { Parallels: 可以将一个win程序拖到mac中运行. } --类似于虚拟机 遇到的几大问题: 1.自动修改无效? --忽略它的存在,坑. 2.无止境的修改,还是错? --使用替换工具-&g ...

  9. 还是畅通project(杭州电1233)

    还是畅通project Time Limit: 4000/2000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others) Tota ...

  10. JAVA异常处理、常用类、反射、集合

    异常 异常:在Java中是指被一个方法抛出的对象. 分类:检查异常.运行时异常.错误 运行时异常(uncheckd):RuntimeException和其子类 检查异常(checkd/搜检异常):指E ...