带进度条的ASP无组件断点续传下载

本文介绍了一种基于ASP的无组件断点续传下载方案,支持XMLHttpRequest异步方式,具备分段下载功能,使用缓冲区提升下载速度,并带有进度条显示下载状态。

<%@LANGUAGE="VBSCRIPT" CODEPAGE="936"%>
<%Option Explicit%>
<%
'=================================='带进度条的ASP无组件断点续传下载''==================================
'简介:
'1)利用xmlhttp方式
'2)无组件
'3)异步方式获取,节省服务器资源
'4)服务器到服务器的文件传送。(当然,你自己电脑上的IIS也是http服务器)
'5)支持断点续传
'6)分段下载
'7)使用缓冲区,提升下载速度
'8)支持大文件下载(速度我就不说了,你可以测,用事实说话)
'9)带进度条:下载百分比、下载量、即时下载速度、平均下载速度
'用法:
'设置好下面的三个变量,RemoteFileUrl、LocalFileUrl、RefererUrl
'作者:午夜狂龙(Madpolice)
'madpolice_dong@163.com
'2005.12.25
'===================================================================================================

'---------------------------------为设置部分---------------------------------
Server.Scripttimeout = 24 * 60 * 60 '脚本超时设置,这里设为24小时
Dim RemoteFileUrl '远程文件路径Dim LocalFileUrl'本地文件路径,相对路径,可以包含/及..
RemoteFileUrl = "http://202.102.14.137/win98.zip"
LocalFileUrl = "win98.zip"
Dim RefererUrl
'该属性设置文件下载的引用页,'某些网站只允许通过他们网站内的连接下载文件,'这些网站的服务器判断用户是否是在他们网站内点击的文件链接就是靠这个属性。RefererUrl = "http://www.skycn.com/crack_skycn.html"'若远程服务器未限制,可留空
Dim BlockSize '分段下载的块大小Dim BlockTimeout'下载块的超时时间(秒)
BlockSize = 128 * 1024 '128K,按1M带宽计算的每秒下载量
(可根据自己的带宽设置,带宽除以8),建议不要设的太小BlockTimeout = 64'应当根据块的大小来设置。这里设为64秒。
如果128K的数据64秒还下载不完(按每秒2K保守估算),则超时。
Dim PercentTableWidth'进度条总宽度
PercentTableWidth = 560
'---------------------------------以上为设置部分---------------------------------

'***********************************'!!!以下内容无须修改!!!'***********************************
Dim LocalFileFullPhysicalPath'本地文件在硬盘上的绝对路径
LocalFileFullPhysicalPath = Server.Mappath(LocalFileUrl)
Dim http,ados
On Error Resume Next
Set http = Server.CreateObject("Msxml2.ServerXMLHTTP.7.0")
If Err Then
 Err.Clear
 Set http = Server.CreateObject("Msxml2.ServerXMLHTTP.6.0")
 
 If Err Then
  Err.Clear
  Set http = Server.CreateObject("Msxml2.ServerXMLHTTP.5.0")
  
  If Err Then
   Err.Clear
   Set http = Server.CreateObject("Msxml2.ServerXMLHTTP.3.0")
   
   If Err Then
    Err.Clear
    Set http = Server.CreateObject("Msxml2.ServerXMLHTTP")
    
    If Err Then
     Err.Clear
     Response.Write "服务器不支持Msxml,本程序无法运行!"
     Response.End
    End If
   End If
  End If
 End If
End If

On Error Goto 0
Set ados = Server.CreateObject("Adodb.Stream")
Dim RangeStart'分段下载的开始位置Dim fso
Set fso = Server.CreateObject("Scripting.FileSystemObject")

If fso.FileExists(LocalFileFullPhysicalPath) Then'判断要下载的文件是否已经存在
 RangeStart = fso.GetFile(LocalFileFullPhysicalPath).Size'若存在,以当前文件大小作为开始位置
Else
 RangeStart = 0'若不存在,一切从零开始
 fso.CreateTextFile(LocalFileFullPhysicalPath).Close'新建文件
End If

Set fso = Nothing

Dim FileDownStart'本次下载的开始位置
Dim FileDownEnd'本次下载的结束位置
Dim FileDownBytes'本次下载的字节数
Dim DownStartTime'开始下载时间
Dim DownEndTime'完成下载时间
Dim DownAvgSpeed'平均下载速度
Dim BlockStartTime'块开始下载时间
Dim BlockEndTime'块完成下载时间
Dim BlockAvgSpeed'块平均下载速度
Dim percentWidth'进度条的宽度
Dim DownPercent'已下载的百分比
FileDownStart = RangeStart
Dim adosCache'数据缓冲区
Dim adosCacheSize'缓冲区大小
Set adosCache = Server.CreateObject("Adodb.Stream")
adosCache.Type = 1'数据流类型设为字节
adosCache.Mode = 3'数据流访问模式设为读写
adosCache.OpenadosCacheSize = 4 * 1024 * 1024'设为4M,获取的数据先放到(内存)缓冲区中,当缓冲区满的时候数据写入磁盘
'若在自己的电脑上运行本程序,当下载百兆以上级别的大文件的时候,可设置大的缓冲区'当然,也不要设的太大,免得发生(按下浏览器上的停止按钮或断电等)意外情况导致缓冲区中的数据没有存盘,那缓冲区中的数据就白下载了
'先显示html头部

Response.Clear
Call HtmlHead()
Response.Flush

Dim ResponseRange'服务器返回的http头中的"Content-Range"
Dim CurrentLastBytes'当前下载的结束位置(即ResponseRange中的上限)
Dim TotalBytes'文件总字节数
Dim temp'分段下载

DownStartTime = Now()
DoBlockStartTime = Timer()
http.open "GET",RemoteFileUrl,true,"",""'用异步方式调用serverxmlhttp

'构造http头
http.setRequestHeader "Referer",RefererUrlhttp.setRequestHeader "Accept","*/*"
http.setRequestHeader "User-Agent","Baiduspider+(+http://www.baidu.com/search/spider.htm)"'伪装成Baidu'
http.setRequestHeader "User-Agent","Googlebot/2.1 (+http://www.google.com/bot.html)"'伪装成Google
http.setRequestHeader "Range","bytes=" & RangeStart & "-" & Cstr(RangeStart + BlockSize - 1)'分段关键
http.setRequestHeader "Content-Type","application/octet-stream"
http.setRequestHeader "Pragma","no-cache"
http.setRequestHeader "Cache-Control","no-cache"
http.send'发送

'循环等待数据接收
While (http.readyState <> 4)'判断是否块超时
 temp = Timer() - BlockStartTime
 
 If (temp > BlockTimeout) Then
  http.abort
  Response.Write "<script>document.getElementById(""status"").innerHTML=""<strong>错误:数据下载超时,建议重试。</strong>"";</script>" & vbNewLine & "</body></html>"
  Call ErrHandler()
  Call CloseObject()
  Response.End
 End If
 
 http.waitForResponse 1000'等待1000毫秒Wend
 
 '检测状态
 If http.status = 416 Then'服务器不能满足客户在请求中指定的Range头。应当是已下载完毕。
  FileDownEnd = FileDownStart'设置一下FileDownEnd,免得后面的FileDownBytes计算出错
  Call CloseObject()
  Exit Do
 End If
 
 '检测状态
 If http.status > 299 Then'http出错
  Response.Write "<script>document.getElementById(""status"").innerHTML=""<strong>http错误:" & http.status & "&nbsp;" & http.statusText & "</strong>"";</script>" & vbNewLine & "</body></html>"
  Call ErrHandler()
  Call CloseObject()
  Response.End
 End If
 
 '检测状态
 If http.status <> 206 Then'服务器不支持断点续传
  Response.Write "<script>document.getElementById(""status"").innerHTML=""<strong>错误:服务器不支持断点续传!</strong>"";</script>" & vbNewLine & "</body></html>"
  Call ErrHandler()
  Call CloseObject()
  Response.End
 End If
 
 '检测缓冲区是否已满
 If adosCache.Size >= adosCacheSize Then'打开磁盘上的文件
  ados.Type = 1'数据流类型设为字节
  ados.Mode = 3'数据流访问模式设为读写
  ados.Openados.LoadFromFile LocalFileFullPhysicalPath'打开文件
  ados.Position = ados.Size'设置文件指针初始位置
  '将缓冲区数据写入磁盘文件
  adosCache.Position = 0ados.Write adosCache.Readados.SaveToFile LocalFileFullPhysicalPath,2'覆盖保存
  ados.Close'缓冲区复位
  adosCache.Position = 0adosCache.SetEOS
 End If
 '保存块数据到缓冲区中
 
 adosCache.Write http.responseBody'写入数据
 
 '判断是否全部(块)下载完毕
 ResponseRange = http.getResponseHeader("Content-Range")'获得http头中的"Content-Range"
 
 If ResponseRange = "" Then'没有它就不知道下载完了没有
  Response.Write "<script>document.getElementById(""status"").innerHTML=""<strong>错误:文件长度未知!</strong>"";</script>" & vbNewLine & "</body></html>"
  Call CloseObject()
  Response.End
 End If
 
 temp = Mid(ResponseRange,Instr(ResponseRange,"-")+1)'Content-Range是类似123-456/789的样子
 CurrentLastBytes = Clng(Left(temp,Instr(temp,"/")-1))'123是开始位置,456是结束位置
 TotalBytes = Clng(Mid(temp,Instr(temp,"/")+1))'789是文件总字节数
 
 If TotalBytes - CurrentLastBytes = 1 Then
  FileDownEnd = TotalBytes'将缓冲区数据写入磁盘文件
  ados.Type = 1'数据流类型设为字节
  ados.Mode = 3'数据流访问模式设为读写
  ados.Openados.LoadFromFile LocalFileFullPhysicalPath'打开文件
  ados.Position = ados.Size'设置文件指针初始位置
  adosCache.Position = 0ados.Write adosCache.Readados.SaveToFile LocalFileFullPhysicalPath,2'覆盖保存
  ados.Close
  Response.Write "<script>document.getElementById(""downsize"").innerHTML=""" & TotalBytes & """;</script>" & vbNewLine
  Response.Flush
  Call CloseObject()
  Exit Do'结束位置比总大小少1就表示传输完成了
 End If'调整块开始位置,准备下载下一个块
 
 RangeStart = RangeStart + BlockSize
 '计算块下载速度、进度条宽度、已下载的百分比
 BlockEndTime = Timer()
 temp = (BlockEndTime - BlockStartTime)
 
 If temp > 0 Then
  BlockAvgSpeed = Int(BlockSize / 1024 / temp)
 Else
  BlockAvgSpeed = ""
 End If
 
 percentWidth = Int(PercentTableWidth * RangeStart / TotalBytes)
 DownPercent = Int(100 * RangeStart / TotalBytes)
 
 '更新进度条
 Response.Write "<script>document.getElementById(""downpercent"").innerHTML=""" & DownPercent & "%"";document.getElementById(""downsize"").innerHTML=""" & RangeStart & """;document.getElementById(""totalbytes"").innerHTML=""" & TotalBytes & """;document.getElementById(""blockavgspeed"").innerHTML=""" & BlockAvgSpeed & """;document.getElementById(""percentdone"").style.width=""" & percentWidth & """;</script>" & vbNewLine
 Response.Flush
Loop

While Response.IsClientConnected
 If Not Response.IsClientConnected Then
  Response.End
 End If
 
 DownEndTime = Now()
 FileDownBytes = FileDownEnd - FileDown
 Starttemp = DateDiff("s",DownStartTime,DownEndTime)
 
 If (FileDownBytes <> 0) And (temp <> 0) Then
  DownAvgSpeed = Int((FileDownBytes / 1024) / temp)
 Else
  DownAvgSpeed = ""
 End If
 
 '全部下载完毕后更新进度条
 Response.Write "<script>document.getElementById(""downpercent"").innerHTML=""100%"";document.getElementById(""percentdone"").style.width=""" & PercentTableWidth & """;document.getElementById(""percent"").style.display=""none"";document.getElementById(""status"").innerHTML=""<strong>下载完毕!用时:" & S2T(DateDiff("s",DownStartTime,DownEndTime)) & ",平均下载速度:" & DownAvgSpeed & "K/秒</strong>"";</script>" & vbNewLine
%>
 </body></html>
<%
 Sub CloseObject()
  Set ados = Nothing
  Set http = Nothing
  adosCache.Close
  Set adosCache = Nothing
 End Sub
 
 'http异常退出处理代码
 Sub ErrHandler()
  Dim fso
  Set fso = Server.CreateObject("Scripting.FileSystemObject")
  
  If fso.FileExists(LocalFileFullPhysicalPath) Then'判断要下载的文件是否已经存在
   If fso.GetFile(LocalFileFullPhysicalPath).Size = 0 Then'若文件大小为0
    fso.DeleteFile LocalFileFullPhysicalPath'删除文件
   End If
  End If
  
  Set fso = Nothing
 End Sub
 
 Sub HtmlHead()
%>
  <html>
  <head>
  <meta http-equiv="Content-Type" content="text/html; charset=gb2312">
  <title>带进度条的ASP无组件断点续传下载----作者:午夜狂龙(Madpolice)--2005.12.25</title>
  </head>
  <body>
  <div id="status">正在下载&nbsp;<span style="color:blue"><%=RemoteFileUrl%></span>&nbsp;,请稍候...</div>
  <div>&nbsp;</div>
  
  <div id="progress">
   已完成:<span id="downpercent" style="color:green"></span>&nbsp;
   <span id="downsize" style="color:red"><%=RangeStart%></span>&nbsp;/&nbsp;
   <span id="totalbytes" style="color:blue"></span>&nbsp;字节(<span id="blockavgspeed"></span>K/秒)
  </div>
  <div>&nbsp;</div>
  
  <div id="percent" align="center" style="display:''">
  <table style="border-collapse:collapse;" border="1" bordercolor="#666666" cellpadding="0" cellspacing="0" width="<%=PercentTableWidth%>" align="center" bgcolor="#eeeeee">
   <tr height="20">
    <td>
     <table border="0" width="" cellspacing="1" bgcolor="#0033FF" id="percentdone">
      <tr>
       <td>&nbsp;<td>
      </tr>
     </table>
    </td>
   </tr>
  </table>
  </div>
<%
 End Sub

'------------------------------'将秒数转换为"x小时y分钟z秒"形式'------------------------------
Function S2T(ByVal s)
 Dim x,y,z,t
 If s < 1 Then
  S2T = (s * 1000) & "毫秒"
 Else
  s = Int(s)
  x = Int(s / 3600)
  t = s - 3600 * x
  y = Int(t / 60)
  z = t - 60 * y
  
  If x > 0 Then
   S2T = x & "小时" & y & "分" & z & "秒"
  Else
   If y > 0 Then
    S2T = y & "分" & z & "秒"
   Else
    S2T = z & "秒"
   End If
  End If
 End If
End Function
'-----------------------
%>

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值