Asp.net中断点续传的原理与实现方法分享
程序员文章站
2024-03-05 18:31:31
请求协议是由客户机 (浏览器)向服务器(web server)提交请求时发送报文的协议。回复协议是由服务器(web server),向客户机(浏览器)回复报文时的协议。请求...
请求协议是由客户机 (浏览器)向服务器(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
相应的响应报文为
http/1.1 206 partial content
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: 1803
content-range: bytes 1024-1803/2827
通过两段不同的报文可以看到,在断点续传时,我们只要能给客户端相应相应的报文,使客户端能正确响应,并且传送续传点后的部分文件即可实现断点续传。
1. 区分断点续传报文。
由于断点续传报文中含有range字段,因此,只要通过request.headers["range"]是否为null即可。
2. 发送正确的续传响应报文
两次响应报文不同的部分在报文中已经用红色部分标识出来,只需修改红色部分报文头,便能发送正确的续传报文。
3. 传送正确的文件部分
续传的时候只需要传送续传点之后的文件即可,首先通过请求报文中的range字段获取文件的开始位置,传送文件的时候只需要传送该位置之后的部分即可。
下面的代码示例显示了一个可以支持断点续传的 asp.net 页
private void page_load(object sender, system.eventargs e)
{
string file = mappath("ff.zip");
fileinfo fi=new fileinfo (file);
long startpos = 0;
//所传输的文件长度
long filetranlen = fi.length;
//断点续传请求
if (request.headers["range"] != null)
{
response.statuscode = 206;
startpos = long.parse(request.headers["range"].replace("bytes=", "").split('-')[0]);
filetranlen -= startpos;
//response.addheader("accept-ranges", "bytes");
//content-range: bytes [文件块的开始字节]-[传输文件的总大小]/[文件的总大小]
response.addheader("content-range", string.format("bytes {0}-{1}/{2}",startpos,filetranlen,fi.length));
}
response.addheader("content-length", filetranlen.tostring());
//基本的文件下载报文头
response.contenttype = "application/octet-stream";
response.addheader("content-disposition", "attachment; filename=" + fi.name);
//简单的流拷贝
system.io.stream filestream = system.io.file.openread(file);
filestream.position = startpos;
byte[] buffer = new byte[1024];
int count;
while ((count = filestream.read(buffer, 0, buffer.length)) > 0)
{
response.outputstream.write(buffer, 0, count);
}
filestream.close();
response.end();
}
以下是一个请求报文与相应的回复报文的例子:
复制代码 代码如下:
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
相应的响应报文为
复制代码 代码如下:
http/1.1 206 partial content
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: 1803
content-range: bytes 1024-1803/2827
通过两段不同的报文可以看到,在断点续传时,我们只要能给客户端相应相应的报文,使客户端能正确响应,并且传送续传点后的部分文件即可实现断点续传。
1. 区分断点续传报文。
由于断点续传报文中含有range字段,因此,只要通过request.headers["range"]是否为null即可。
2. 发送正确的续传响应报文
两次响应报文不同的部分在报文中已经用红色部分标识出来,只需修改红色部分报文头,便能发送正确的续传报文。
3. 传送正确的文件部分
续传的时候只需要传送续传点之后的文件即可,首先通过请求报文中的range字段获取文件的开始位置,传送文件的时候只需要传送该位置之后的部分即可。
下面的代码示例显示了一个可以支持断点续传的 asp.net 页
复制代码 代码如下:
private void page_load(object sender, system.eventargs e)
{
string file = mappath("ff.zip");
fileinfo fi=new fileinfo (file);
long startpos = 0;
//所传输的文件长度
long filetranlen = fi.length;
//断点续传请求
if (request.headers["range"] != null)
{
response.statuscode = 206;
startpos = long.parse(request.headers["range"].replace("bytes=", "").split('-')[0]);
filetranlen -= startpos;
//response.addheader("accept-ranges", "bytes");
//content-range: bytes [文件块的开始字节]-[传输文件的总大小]/[文件的总大小]
response.addheader("content-range", string.format("bytes {0}-{1}/{2}",startpos,filetranlen,fi.length));
}
response.addheader("content-length", filetranlen.tostring());
//基本的文件下载报文头
response.contenttype = "application/octet-stream";
response.addheader("content-disposition", "attachment; filename=" + fi.name);
//简单的流拷贝
system.io.stream filestream = system.io.file.openread(file);
filestream.position = startpos;
byte[] buffer = new byte[1024];
int count;
while ((count = filestream.read(buffer, 0, buffer.length)) > 0)
{
response.outputstream.write(buffer, 0, count);
}
filestream.close();
response.end();
}