[心缘地方]同学录
首页 | 功能说明 | 站长通知 | 最近更新 | 编码查看转换 | 代码下载 | 常见问题及讨论 | 《深入解析ASP核心技术》 | 王小鸭自动发工资条VBA版
登录系统:用户名: 密码: 如果要讨论问题,请先注册。

[ASP备忘]使用Adodb.stream下载文件,支持多线程断点续传……

上一篇:[备忘]查询域名的实际注册商的方法
下一篇:[本站胡乱翻译]Oracle Objects for OLE (OO4O)简介……

添加日期:2007/7/14 22:55:27 快速返回   返回列表 阅读5343次
以前的一段代码,只是分析了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了。


知道了以上原理,就可以进行断点续传的编程了。
============================================================
 

评论 COMMENTS
没有评论 No Comments.

添加评论 Add new comment.
昵称 Name:
评论内容 Comment:
验证码(不区分大小写)
Validation Code:
(not case sensitive)
看不清?点这里换一张!(Change it here!)
 
评论由管理员查看后才能显示。the comment will be showed after it is checked by admin.
CopyRight © 心缘地方 2005-2999. All Rights Reserved