惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

Forbes - Security
Forbes - Security
GbyAI
GbyAI
OSCHINA 社区最新新闻
OSCHINA 社区最新新闻
S
SegmentFault 最新的问题
Y
Y Combinator Blog
Recorded Future
Recorded Future
博客园 - Franky
I
InfoQ
T
The Blog of Author Tim Ferriss
Recent Announcements
Recent Announcements
Cyber Security Advisories - MS-ISAC
Cyber Security Advisories - MS-ISAC
博客园_首页
阮一峰的网络日志
阮一峰的网络日志
T
Tailwind CSS Blog
Cyberwarzone
Cyberwarzone
The Register - Security
The Register - Security
H
Hackread – Cybersecurity News, Data Breaches, AI and More
Threat Intelligence Blog | Flashpoint
Threat Intelligence Blog | Flashpoint
雷峰网
雷峰网
P
Palo Alto Networks Blog
G
GRAHAM CLULEY
Cloudbric
Cloudbric
CTFtime.org: upcoming CTF events
CTFtime.org: upcoming CTF events
MongoDB | Blog
MongoDB | Blog
F
Full Disclosure
Google DeepMind News
Google DeepMind News
Recent Commits to openclaw:main
Recent Commits to openclaw:main
C
Check Point Blog
爱范儿
爱范儿
The GitHub Blog
The GitHub Blog
cs.AI updates on arXiv.org
cs.AI updates on arXiv.org
W
WeLiveSecurity
T
Threat Research - Cisco Blogs
U
Unit 42
N
Netflix TechBlog - Medium
The Cloudflare Blog
Spread Privacy
Spread Privacy
Microsoft Azure Blog
Microsoft Azure Blog
美团技术团队
T
Troy Hunt's Blog
Engineering at Meta
Engineering at Meta
H
Heimdal Security Blog
TaoSecurity Blog
TaoSecurity Blog
C
Cybersecurity and Infrastructure Security Agency CISA
T
Tenable Blog
B
Blog
S
Securelist
H
Hacker News: Front Page
Google Online Security Blog
Google Online Security Blog
G
Google Developers Blog

博客园 - dahai.net

常用的DOCUMENT.EXECCOMMAND WebForm中的tip - dahai.net - 博客园 修改所有用户表/存储过程/视图/触发器/自定义函数的所有者为dbo,则用游标(不要理会错误提示) 在无锡办理10万元注册资本的企业,所需要时间和费用 Win 2003下无敌权限提升方法(转) ftp讨论站连接 使用WMI创建站点和虚拟目录,并设置属性 - dahai.net - 博客园 千万数据翻页解决方案 CHM格式解析 从互联网加载图片到PictureBox1 Visual Studio .NET已检测到指定的Web服务器运行的不是ASP.NET 1.1 版 - dahai.net [分享]千万数量级分页存储过程(带效果演示)(转) 网站分析专用名词 列出sqlserver数据库孤立用户 写数据到文件 - dahai.net - 博客园 网页模糊归类算法的应用与实现 搜索引擎的实现原理 总结字符串编码(转) 一种快速的未登陆词识别方法(原理和实现)
使用.NET实现断点续传
dahai.net · 2006-05-25 · via 博客园 - dahai.net

ivy_live521(原作)

断点续传的原理
在了解HTTP断点续传的原理之前,先来说说HTTP协议,HTTP协议是一种基于tcp的简单协议,分为请求和回复两种。请求协议是由客户机(浏览器)向服务器(WEB SERVER)提交请求时发送报文的协议。回复协议是由服务器(web server),向客户机(浏览器)回复报文时的协议。请求和回复协议都由头和体组成。头和体之间以一行空行为分隔。
以下是一个请求报文与相应的回复报文的例子:
GET /image/index_r4_c1.jpg HTTP/1.1
Accept: */*
Referer: http://192.168.3.120:8080
Accept-Language: zh-cn
Accept-Encoding: gzip, deflate
User-Agent: Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; .NET CLR 1.0.3705)
Host: 192.168.3.120:8080
Connection: Keep-Alive

HTTP/1.1 200 OK
Server: Microsoft-IIS/5.0
Date: Tue, 24 Jun 2003 05:39:40 GMT
Content-Type: image/jpeg
Accept-Ranges: bytes
Last-Modified: Thu, 23 May 2002 03:05:40 GMT
ETag: "bec48eb862c21:934"
Content-Length: 2827
….

下面我们就来说说“断点续传”。
顾名思义,断点续传就是在上一次下载时断开的位置开始继续下载。在HTTP协议中,可以在请求报文头中加入Range段,来表示客户机希望从何处继续下载。
比如说从第1024字节开始下载,请求报文如下:

GET /image/index_r4_c1.jpg HTTP/1.1
Accept: */*
Referer: http://192.168.3.120:8080
Accept-Language: zh-cn
Accept-Encoding: gzip, deflate
User-Agent: Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; .NET CLR 1.0.3705)
Host: 192.168.3.120:8080
Range:bytes=1024-
Connection: Keep-Alive

 .NET中的相关类
明白了上面的原理,那么,我们来看看.NET FRAMEWORK中为我们提供了哪些类可以来做这些事。

完成HTTP请求
System.Net.HttpWebRequest

HttpWebRequest 类对 WebRequest 中定义的属性和方法提供支持,也对使用户能够直接与使用 HTTP 的服务器交互的附加属性和方法提供支持。

HttpWebRequest 将发送到 Internet 资源的公共 HTTP 标头值公开为属性,由方法或系统设置。下表包含完整列表。可以将 Headers 属性中的其他标头设置为名称/值对。但是注意,某些公共标头被视为受限制的,它们或者直接由 API公开,或者受到系统保护,不能被更改。Range也属于被保护之列,不过,.NET为开发者提供了更方便的操作,就是 AddRange方法,向请求添加从请求数据的开始处或结束处的特定范围的字节范围标头

完成文件访问
System.IO.FileStream

FileStream 对象支持使用Seek方法对文件进行随机访问, Seek 允许将读取/写入位置移动到文件中的任意位置。这是通过字节偏移参考点参数完成的。字节偏移量是相对于查找参考点而言的,该参考点可以是基础文件的开始、当前位置或结尾,分别由SeekOrigin类的三个属性表示。


代码实现
了解了.NET提供的相关的类,那么,我们就可以方便的实现了。

代码如下:

static void Main(string[] args)
              
{
                     
string StrFileName="c:\\aa.zip";      //根据实际情况设置
                     string StrUrl="http://www.xxxx.cn/xxxxx.zip";   //根据实际情况设置


                     
//打开上次下载的文件或新建文件
                     long lStartPos =0;
                     System.IO.FileStream fs;
                     
if (System.IO.File.Exists(StrFileName))
                     
{
                            fs
= System.IO.File.OpenWrite(StrFileName);
                            lStartPos
=fs.Length;
                            fs.Seek(lStartPos,System.IO.SeekOrigin.Current);   
//移动文件流中的当前指针
                     }

                     
else
                     
{
                            fs 
= new System.IO.FileStream(StrFileName,System.IO.FileMode.Create);
                            lStartPos 
=0;
                     }

                     
//打开网络连接
                     try
                     
{
                            System.Net.HttpWebRequest request 
=(System.Net.HttpWebRequest)System.Net.HttpWebRequest.Create(StrUrl);
                            
if ( lStartPos>0)
                                   request.AddRange((
int)lStartPos);    //设置Range值
                            
//向服务器请求,获得服务器回应数据流
                            System.IO.Stream ns= request.GetResponse().GetResponseStream();
                            
byte[] nbytes = new byte[512];
                            
int nReadSize=0;
                            nReadSize
=ns.Read(nbytes,0,512);
                            
while( nReadSize >0)
                            
{
                                   fs.Write(nbytes,
0,nReadSize);
                                   nReadSize
=ns.Read(nbytes,0,512);
                            }

                            fs.Close();
                            ns.Close();
                            Console.WriteLine(
"下载完成");
                     }

                     
catch(Exception ex)
                     
{
                            fs.Close();
                            Console.WriteLine(
"下载过程中出现错误:"+ex.ToString());
                     }

              }