用HttpListener实现文件断点续传
2008-05-14 13:30
267 查看
断点续传的原理很简单,就是在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); //模拟慢速设备
}
}
普通方式请求服务器上的一个文时,所发出的请求和接受到的服务器如下:
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); //模拟慢速设备
}
}
相关文章推荐
- 用HttpListener实现文件断点续传
- ASP.NET用HttpListener实现文件断点续传
- 用HttpListener 建立web服务器 实现网页浏览、文件上传
- 利用TIdHttp实现文件下载的分块断点续传
- 用PHP实现 HTTP断点续传、分块下载文件(Socket)
- HttpURLConnection实现文件断点续传
- 用HttpListener实现文件下载
- C#利用HttpListener实现接受上传文件
- delphi IdHTTP实现Get方法下载文件,断点续传
- 请问 Android http上传文件 可以断点续传么 如果可以怎么实现 有第三方的插件么 谢谢
- 请问 Android http上传文件 可以断点续传么 如果可以怎么实现 有第三方的插件么 谢谢
- HttpURLConnection方式下载文件之实现断点续传
- 利用XMLHttpRequest技术实现断点续传下载文件
- 用HttpListener实现文件下载
- 用HttpListener实现文件断点续传
- HttpWebRequest实现文件下载(断点续传)
- Windows Winnet 实现HTTP 文件断点续传下载
- epoll+线程池实现http文件下载
- 通过HttpListener实现简单的Http服…
- .NET用HttpFileCollection实现多文件上传