以前的一段代码,只是分析了HTTP Header中的Range而已,用网络蚂蚁下载时,显示的是灰色的圈,根本就不能断点续传。
大概代码如下:
Set objStream=CreateObject("Adodb.Stream") objStream.Mode=3 objStream.Type=1 '返回的数据类型为二进制 objStream.Open objStream.LoadFromFile(fileSpec) Response.ContentType="application/octet-stream" if downFileFlg="Y" then Response.AddHeader "Content-Disposition:","attachment; filename=" & Server.URLpathencode(fileName) &"."&fileExtension else Response.AddHeader "Content-Disposition:","inline; filename=" & Server.URLpathencode(fileName) &"."&fileExtension end if If Not Response.IsClientConnected Then objStream.Close Set objStream = Nothing Response.End end if Response.AddHeader "content-length", objStream.Size Range=Mid(Request.ServerVariables("HTTP_RANGE"),7) if Range="" then Response.BinaryWrite(objStream.Read) else objStream.position=Clng(Split(Range,"-")(0)) Response.BinaryWrite(objStream.Read) End if If Not Response.IsClientConnected Then objStream.Close Set objStream = Nothing Response.End end if objStream.Close Set objStream = Nothing Response.End
(1)纳闷,网络蚂蚁是如何判断服务端是否支持断点续传的,搜索后
得知,从指定位置写出数据时,应返回状态:206 Partial Content
即:response.status="206 Partial Content"
这样,网络蚂蚁就知道,服务端是支持断点续传的,那个小圈变成彩色的了……
(2)如上修改后,蚂蚁的第2个及以后的线程,报:
在服务器的回应中存在损坏的内容范围
很容易的想到了,响应信息中的Content-Range设置的不对。
也就是这东西: ----------------------------------------------------- 2007/07/14 20:10:45 Accept-Ranges: bytes 6162432-15406570/15406570 2007/07/14 20:10:45 content-length: 9244139 -----------------------------------------------------
照葫芦画瓢:
rangeStart = Clng(Split(Range,"-")(0)) Response.AddHeader "Content-Range", "bytes " & rangeStart & "-" & fullSize & "/" & fullSize Response.AddHeader "content-length", cstr(fullSize-rangeStart+1)
没想到,执行下载,还是那句话…………百思不得其解…………
后来,用蚂蚁下载了几个其他文件,看蚂蚁的传输LOG,逐项对比
发现人家的类似这样: ----------------------------------------------------- 2007/07/14 20:10:45 Accept-Ranges: bytes 6162432-15406569/15406570 2007/07/14 20:10:45 content-length: 9244138 ----------------------------------------------------- 注意数字,范围的结束那个数应该是总大小减一,不知道为啥。
content-length就是总大小-起始数,没加一……
修改后,OK……
(3)但是,我测试的是用一个wmv文件,用蚂蚁下载后,文件打不开……
用二进制对比工具对比,发现数据与原始不同……
后又发现,用IE直接下载没问题,用迅雷下载没问题。
用一只蚂蚁下载也有问题……
表现为:数据开头多3个字节:6330 3030 0D0A,文件末端好像也不对……
但文件总大小是正确的……
又试了txt,htm等文件,开头总是多2-3个字节,内容还不同,末端也很乱。
不知道为啥了……挠头中……
============================================================= [2008/03/25添加] 问题解决了,多个蚂蚁同时下载没问题了。
最终的部分代码如下,供参考:
response.buffer=true '输出缓冲开启,这是重点!! '---开始下载文件------------------- Set objStream=CreateObject("Adodb.Stream") objStream.Mode=3 objStream.Type=1 '返回的数据类型为二进制 objStream.Open objStream.LoadFromFile(fileSpec) Response.ContentType="application/octet-stream" if downFileFlg="Y" then Response.AddHeader "Content-Disposition:","attachment; filename=" & Server.URLencode(fileName) else Response.AddHeader "Content-Disposition:","inline; filename=" & Server.URLencode(fileName) end if If Not Response.IsClientConnected Then objStream.Close Set objStream = Nothing Response.End end if Range=Mid(Request.ServerVariables("HTTP_RANGE"),7) '---多线程下载--- fullSize=objStream.Size if Range="" then Response.AddHeader "content-length", fullSize ' Response.AddHeader "Accept-Ranges", "bytes" else Response.Status="206 Partial Content" rangeStart = Clng(Split(Range,"-")(0)) Response.AddHeader "Content-Range", "bytes " & rangeStart & "-" & (fullSize-1) & "/" & fullSize Response.AddHeader "content-length", cstr(fullSize-rangeStart) ' Response.AddHeader "Accept-Ranges", "bytes" objStream.position=rangeStart End if '---防止占满缓冲区,循环分块写出---- iCount=0 '计数 readBlockSize=1024*48 '48K readBlock=objStream.Read(readBlockSize) do while Lenb(readBlock)>0 Response.BinaryWrite readBlock Response.Flush readBlock=objStream.Read(readBlockSize) iCount=iCount+1 if (iCount mod 16) =0 then '每16次检查一次连接状态。 If Not Response.IsClientConnected Then objStream.Close set objStream = Nothing Response.End end if end if loop objStream.Close Set objStream = Nothing Response.End
============================================================= 以下转文:
钟华 (zhong_hua@263.net) 2001 年 5 月
(一)断点续传的原理
其实断点续传的原理很简单,就是在Http的请求上和一般的下载有所不同而已。 打个比方,浏览器请求服务器上的一个文时,所发出的请求如下: 假设服务器域名为wwww.sjtu.edu.cn,文件名为down.zip。
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
服务器收到请求后,按要求寻找请求的文件,提取文件的信息,然后返回给浏览器,返回信息如下:
200 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
所谓断点续传,也就是要从文件已经下载的地方开始继续下载。所以在客户端浏览器传给 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字节开始传,前面的字节不用传了。 服务器收到这个请求以后,返回的信息如下:
206 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了。
知道了以上原理,就可以进行断点续传的编程了。 ============================================================
|