Http 206 文件断点续传下载原理
2016-10-14 09:01
891 查看
Http 206 文件断点续传下载原理
收藏
IamOkay
发表于 2年前
阅读 8182
收藏 218
点赞 7
评论
12
摘要: Http 206 文件断点续传下载原理
HTTP 304/200(from cache) 静态资源缓存原理
HTTP 204/205状态响应&HEAD请求
header标头说明
断点续传下载需要重视2个请求头Range与If-Range
打个比方,浏览器请求服务器上的一个文时,所发出的请求如下:
假设服务器域名为www.ksTest.com,文件名为down.zip。
1.1不使用断点续传
服务器收到请求后,按要求寻找请求的文件,提取文件的信息,然后返回给浏览器,返回信息如下:
2.使用断点续传
所谓断点续传,也就是要从文件已经下载的地方开始继续下载。所以在客户端浏览器传给web服务器的时候要多加一条信息--从哪里开始。
下面是用自己编的一个“浏览器”来传递请求信息给web服务器,要求从2000070字节开始。
仔细看一下就会发现多了一行
这一行的意思就是告诉服务器down.zip这个文件从2000070字节开始传,前面的字节不用传了。
Range的完整格式是
服务器收到这个请求以后,返回的信息如下:
和前面服务器返回的信息比较一下,就会发现增加了一行:
返回的代码也改为206了,而不再是200了。
以上信息不需要后台程序返回,而是服务器直接读取信息返回给client
知道了以上原理,就可以进行断点续传的编程了。
Client端代码如下
1.在PHP文件下载所需要的头信息
下面是一个简单的PHP下载文件的示例
2.用代码控制断点续传
部分服务器支持断点续传,但是前提是必须保证如下格式请求头才行,否则无法断点续传,只能是http 200正常下载
[b]3.3关于If-Range增强断点续传验证测试[/b]
不设置If-Range的时候
设置If-Range的时候
3.3使用If-Modified-Since & If-None-Match
[b]If-Modified-Since传递时间[/b]
[b][b]If-None-Match传递etag,不会出现http 412问题[/b][/b]
简单来说,if-Range是上述两者的综合体,因此,在实际项目中,请根据需要使用哪一种请求头。
© 著作权归作者所有
分类:Network
字数:1828
标签: IIS断点续传
Http206断点续传
文件下载
文件续传
Range
If-Range
If-Match
收藏
IamOkay
发表于 2年前
阅读 8182
收藏 218
点赞 7
评论
12
摘要: Http 206 文件断点续传下载原理
HTTP 304/200(from cache) 静态资源缓存原理
HTTP 204/205状态响应&HEAD请求
header标头说明
断点续传下载需要重视2个请求头Range与If-Range
一.断点续传的原理
其实断点续传的原理很简单,就是在http的请求上和一般的下载有所不同而已。打个比方,浏览器请求服务器上的一个文时,所发出的请求如下:
假设服务器域名为www.ksTest.com,文件名为down.zip。
1.1不使用断点续传
get /down.zip http/1.1 accept: image/gif, image/x-xbitmap, image/jpeg, image/pjpeg, application/vnd.ms- excel, application/msword, application/vnd.ms-powerpoint, */* accept-language: zh-cn accept-encoding: gzip, deflate user-agent: mozilla/4.0 (compatible; msie 5.01; windows nt 5.0) connection: keep-alive
服务器收到请求后,按要求寻找请求的文件,提取文件的信息,然后返回给浏览器,返回信息如下:
HTTP/1.1 200 Ok content-length=106786028 accept-ranges=bytes date=mon, 30 apr 2001 12:56:11 gmt etag=w/"02ca57e173c11:95b" content-type=application/octet-stream server=microsoft-iis/5.0 last-modified=mon, 30 apr 2001 12:56:11 gmt
2.使用断点续传
所谓断点续传,也就是要从文件已经下载的地方开始继续下载。所以在客户端浏览器传给web服务器的时候要多加一条信息--从哪里开始。
下面是用自己编的一个“浏览器”来传递请求信息给web服务器,要求从2000070字节开始。
get /down.zip http/1.0 User-Agent: netfox Range: bytes=2000070- accept: text/html, image/gif, image/jpeg, *; q=.2, */*; q=.2
仔细看一下就会发现多了一行
Range: bytes=2000070-
这一行的意思就是告诉服务器down.zip这个文件从2000070字节开始传,前面的字节不用传了。
Range的完整格式是
Range: bytes=startOffset-targetOffset/sum [表示从startOffset读取,一直读取到targetOffset位置,读取总数为sum直接] Range: bytes=startOffset-targetOffset [字节总数也可以去掉]
服务器收到这个请求以后,返回的信息如下:
HTTP/1.1 206 Partial Content content-length=106786028 content-range=bytes 2000070-106786027/106786028 date=mon, 30 apr 2001 12:55:20 gmt etag=w/"02ca57e173c11:95b" content-type=application/octet-stream server=microsoft-iis/5.0 last-modified=mon, 30 apr 2001 12:55:20 gmt
和前面服务器返回的信息比较一下,就会发现增加了一行:
Content-Range=bytes 2000070-106786027/106786028
返回的代码也改为206了,而不再是200了。
HTTP/1.1 206 Partial Content
以上信息不需要后台程序返回,而是服务器直接读取信息返回给client
知道了以上原理,就可以进行断点续传的编程了。
Client端代码如下
try { URL url = new URL("http://img5.duitang.com/uploads/item/201203/16/20120316164401_tyAVV.thumb.700_0.jpeg"); File targetFile = new File("test.jpeg"); HttpURLConnection openConnection = (HttpURLConnection) url.openConnection(); openConnection.setRequestMethod("POST"); if(targetFile.exists()) { openConnection.addRequestProperty("Range", "bytes="+targetFile.length()+"-"); }else{ openConnection.addRequestProperty("Range", "bytes=0-"); } openConnection.connect(); int responseCode = openConnection.getResponseCode(); Map<String, List<String>> headerFields = openConnection.getHeaderFields(); System.out.println(headerFields); if(responseCode==200 || responseCode==206) { InputStream is = openConnection.getInputStream(); FileOutputStream fos = new FileOutputStream(targetFile); int len = -1; byte[] buf = new byte[1024]; while((len=is.read(buf,0,1024))>0) { fos.write(buf, 0, len); break;//为了便于测试,每次只读取一次 } fos.close(); is.close(); } } catch (IOException e) { e.printStackTrace(); }
二.使用代码控制断点续传
文件下载原理主要控制来自于服务器端响应,浏览器或者httpClient自行读取IO流1.在PHP文件下载所需要的头信息
Accept-Ranges:bytes #接受类型 Access-Control-Allow-Origin:* #允许任何主机均可跨域访问,ajax同样可以 Access-Control-Max-Age:2592000 Cache-Control:public, max-age=31536000 Connection:keep-alive Content-Disposition:attachment; filename="c501b_01_h264_sd_960_540.mp4" Content-Length:14470485 Content-Transfer-Encoding:binary #传输类型,字节类型 Content-Type:video/mp4 #响应类型 Date:Sun, 25 Jan 2015 00:17:14 GM #文件日期--注意,对于浏览器读取缓存而不重新请求服务器十分有用,用来检测静态文件有没有被修改 ETag:"lraEcGPNv-73F2tLNOKhuA8a6pFa" #
下面是一个简单的PHP下载文件的示例
2.用代码控制断点续传
<?php function smartReadFile( $filepath, $mimeType='application/octet-stream') { date_default_timezone_set('GMT'); //注意时区必须是GMT,否则可能产生错误缓存 $filepath=iconv("utf-8","gb2312",$filepath); if(!file_exists($filepath)) { header ("HTTP/1.0 404 Not Found"); return; } $size=filesize($filepath); $time=date('D, j M Y H:i:s e',filemtime($filepath)); //转为格林尼治时间,同时注意php中文件时间写入的函数是 touch $fm=@fopen($filepath,'rb'); //测试能否打开文 if(!$fm) { header ("HTTP/1.0 505 Internal server error"); return; } $stat = stat($filepath); $md5str = md5_file($filepath); //使用md5校验,更加精确 $etag = $md5str.'-'.sprintf('%x-%x-%x', $stat['ino'], $stat['size'], $stat['mtime'] * 1000000); if(isset($_SERVER['HTTP_IF_RANGE']) && (($_SERVER['HTTP_IF_RANGE'] == $etag) || (strtotime($_SERVER['HTTP_IF_RANGE']) >= $stat['mtime']))) { header('Etag: "' . $etag . '"'); header('Last-Modified: ' . date('D, j M Y H:i:s e', $stat['mtime'])); header('HTTP/1.0 304 Not Modified'); return ; } if(isset($_SERVER['HTTP_IF_NONE_MATCH']) && $_SERVER['HTTP_IF_NONE_MATCH'] == $etag) { header('Etag: "' . $etag . '"'); header('HTTP/1.0 304 Not Modified'); return ; } elseif(isset($_SERVER['HTTP_IF_MODIFIED_SINCE']) &&strtotime($_SERVER['HTTP_IF_MODIFIED_SINCE']) >= $stat['mtime']) { header('Last-Modified: ' . date('D, j M Y H:i:s e', $stat['mtime'])); header('HTTP/1.0 304 Not Modified'); return; } $begin=0; $end=$size; if(isset($_SERVER['HTTP_RANGE'])) { if(preg_match('/bytes=\h*(\d+)-(\d*)[\D.*]?/i', $_SERVER['HTTP_RANGE'], $matches)) { $begin=intval($matches[0]); if(!empty($matches[1])) $end=intval($matches[1]); } } if($begin>0||$end<$size) header('HTTP/1.0 206 Partial Content'); else header('HTTP/1.0 200 OK'); header("Content-Type: $mimeType"); //指定文件minetype,//注意,部分浏览器mineType需要明确指定(如image/png),否则不能下载 header('Cache-Control: public, must-revalidate, max-age=0'); //控制client缓存,要求不缓存 header('Pragma: no-cache'); header('Accept-Ranges: bytes'); //表示浏览器接受bytes的断点续传 header('Content-Length:'.($end-$begin)); //如果未指定长度,这以chunked编码传输文件到客户端 header("Content-Range: bytes $begin-$end/$size"); header("Content-Disposition: attachment; filename=".basename($filepath).""); //文件下载 header('Content-Description: File Transfer');//非标准头信息,可以不要 header("Content-Transfer-Encoding: binary\n"); //非标准头信息,可以不要 header("Last-Modified: $time"); //用于校验 header('Etag: "' . $etag . '"'); header('Connection: close'); $cur=$begin; fseek($fm,$begin,0); //将指针定位到要读取的位置 while(!feof($fm)&&$cur<$end&&(connection_status()==0)) { echo fread($fm,min(1024*16,$end-$cur)); $cur+=1024*16; } fclose($fm); } $file = './test.png'; $exts = get_loaded_extensions(); $mimeType = 'application/octet-stream'; if(array_search('fileinfo', $exts)===FALSE) { $sizeInfo = getimagesize($file); $mimeType = $sizeInfo['mime']; }else{ $mimeType = mime_content_type($file); } smartReadFile($file,$mimeType); ?>
三.服务器断点续传文件增强验证(If-Range,If-Match)
3.1使用if-Range进行增强校验部分服务器支持断点续传,但是前提是必须保证如下格式请求头才行,否则无法断点续传,只能是http 200正常下载
If-Range: "40e04a44a997d11:0" //第一次获取到的Etag的值 //If-Range: "Sat, 16 Apr 2016 06:29:02 GMT"//或者是Last-Modified的值
#对于IIS服务器 1.我们下载中断的时候一定要把得到的Last-Modified和Etag写入文件meta信息中,但是很多情况下ETag无法写入文件meta信息,因此,我们要确保last-Modifield被保存 2.注意,使用时间必须是格林尼治时间
3.2使用if-Match进行增强校验与Http412问题
当然使用if-Match也是一种方式,但是,如果服务器端的资源被修改了,那么,http请求时http 412,因此,我们建议使用iF-Range,这样,即时文件被修改,也会以http200返回全部资源。If-Match: "40e04a44a997d11:0" //第一次获取到的Etag的值
[b]3.3关于If-Range增强断点续传验证测试[/b]
不设置If-Range的时候
设置If-Range的时候
[b]If-Modified-Since传递时间[/b]
[b][b]If-None-Match传递etag,不会出现http 412问题[/b][/b]
简单来说,if-Range是上述两者的综合体,因此,在实际项目中,请根据需要使用哪一种请求头。
四.关于在浏览器中显示文件内容
浏览器默认会显示一些 text/*,image/*,PDF类型的文件,但默认会变成自动下载,这是我们需要修改响应头为Content-Disposition:inline; filename="c501b_01_h264_sd_960_540.mp4"
© 著作权归作者所有
分类:Network
字数:1828
标签: IIS断点续传
Http206断点续传
文件下载
文件续传
Range
If-Range
If-Match
相关文章推荐
- Http 206 文件断点续传下载原理
- Http 206 文件断点续传下载原理
- http协议 文件下载原理及多线程断点续传
- http断点续传与文件下载原理解析
- 利用TIdHttp实现文件下载的分块断点续传
- 断点续传的原理在Http的请求上和一般的下载有所不同而已
- 文件下载原理详解 http协议
- HttpWebRequest实现文件下载(断点续传)
- java中怎样利用http断点续传的原理下载
- 反射机制及开源框架xUitls的使用,使用HttpUtils通过断点续传下载文件
- C# 文件Http断点续传下载公共类
- http协议 文件下载原理详解
- C#Http文件下载(支持断点续传) 提供资源下载
- HTTP文件断点续传的原理
- [转载]http协议 文件下载原理及多线程断点续传
- HTTP文件断点续传的原理
- delphi IdHTTP实现Get方法下载文件,断点续传
- 自定义文件下载支持断点续传(HTTP_RANGE Adodb.Stream)
- HTTP文件下载原理
- Windows Winnet 实现HTTP 文件断点续传下载