为了正常的体验网站,请在浏览器设置里面开启Javascript功能!
首页 > VFP实现HTTP带进度条的断点下载

VFP实现HTTP带进度条的断点下载

2018-09-22 14页 doc 47KB 39阅读

用户头像

is_995397

暂无简介

举报
VFP实现HTTP带进度条的断点下载VFP实现HTTP带进度条的断点下载 最近写一个小东西,要求有在线更新功能,碰到这样的问题首先想到了Msxml2.XMLHTTP和ADODB.Stream,最后同步下载到是实现了,但却被异步下载难倒了,后来找了大量的VC、VB、ASP、.NET等代码来参考,但始终很难在VF上直接实现,后来又转想到了WININET(Microsoft Internet Transfer C ontrol )控件,大家知道inet也有同步和异步两种方式,我们常用的获得网页源码的方法如: thisform.inet.openurl('www.1...
VFP实现HTTP带进度条的断点下载
VFP实现HTTP带进度条的断点下载 最近写一个小东西,要求有在线更新功能,碰到这样的问题首先想到了Msxml2.XMLHTTP和ADODB.Stream,最后同步下载到是实现了,但却被异步下载难倒了,后来找了大量的VC、VB、ASP、.NET等代码来参考,但始终很难在VF上直接实现,后来又转想到了WININET(Microsoft Internet Transfer C ontrol )控件,大家知道inet也有同步和异步两种方式,我们常用的获得网页源码的方法如: thisform.inet.openurl('www.163.com')这样我们就得到了163主页的源代码,同样thisform.inet.openurl('',1) 这样的话我们就获得了ydgl.rar文件的全部内容,再新建立一个文件把得到的内容写进去就算是把ydgl.rar这个文件下载下来了,但是这样做是一次性把整个文件的内容全部下载,没办法实现进度表达,所以我们要采用异步方式来获取,也就是inet.execute(url),知道了这些就可以写代码了: 实现进度显示的步骤: 1、首先获取被下载文件的大小 我们知道在访问一个URL的时候会首先返回一个HTTP头文件,这文件头里包含有被下载文件相关重要信息,如这样一个THHP头: HTTP/1.1 200 OK Server: Microsoft-IIS/5.0 Date: Wed, 16 Aug 2006 09:20:34 GMT Content-Type: application/octet-stream Accept-Ranges: bytes Last-Modified: Mon, 14 Aug 2006 01:50:10 GMT ETag: "3ac82dfa43bfc61:dae" Content-Length: 10248 这里的Content-Length头部分显示的就是我们要下载文件的大小,这个数值我们可以用 inet.getheader(‘Content-Length’)来获得。 获得被下载文件大小的代码: inet. execute(url) inet.getheader(‘Content-Length’)&&返回文件大小,字符型。 2、按段下载数据 知道了文件的大小,接下来就是要一段一段的来获取文件的数据,比如已知一个文件的大小是10M(10*1024*1024bety),我们下载的时候每次按1024KB来下载,那么一共要下载10次才能下载完,如果我们把这10次下载的任务交给10个inet去完成,那就变成了‘多线程’下载了,当然这里的‘多线程’实际上是多任务下载不是真正的多线程。 inet.execute(url,'get',,’ Range: bytes=0-’)这句的意思是获取被下载文件的头部一直尾部的全部数据,也就是整个文件。 inet.execute(url,'get',,’ Range: bytes=1024-2101’)这句的意思是获取被下载文 件的1024字节到2101字节的部数据。 这样我们就可以很好的给inet分配下载段了。 inet.execute()获取了数据后,我们再用inet.GetChunk(size,1)来从缓冲区获取数据,这里的size是指你要获得的字节数。 这样我们就可以一段一段的下载文件了,实现进度条显示就解决了 3、显示进度信息 进度信息基本上靠一个timer就能刷新下载剩余量、下载百分比、下载剩余时间等进度信息了,这里就不多说了。 4、一些需要注意的地方 a. 分段下载的过程是个循环下载的过程,但我们却不能用for或者do whil这样的循环去操作,因为下载每一断的时候都是有延时的,由于VF是单线程顺序执行代码,所以这样操作一般都会失败,那么我们就采用计数变量来不逐一循环激发 inet.execute ()和inet.GetChunk(),比如我们是分100段来下载文件,当计数变量<=100的情况下就循环激发,也就是 inet.GetChunk()后再去激发inet.execute()然后inet.execute()又去激发inet.GetChunk(),达到 100的时候我们再看下这时候文件是否全部下载完毕,如果没有那么再把剩下的数据补进去就行了。 b.inet.GetChunk()获取的数据类型是和文件数据类型一致的,所以我们直接fcraete()建立一个文件,然后把获得数据直接fwrite() 就可以了。 c.一般最少用两个inet来操作会更方便点,一个是获取文件信息,一个是专门下载数据。 d. 每个inet执行结束后最好inet.objiect.cancel,因为有些被下载的文件不支持多线程下载。 e.段点续载你可以象flashget等软件先建立一个自己的文件结构,等下载完毕后再还原文件,如果补这样的话,比如有和你上次没下载完的文件同名的文件就补会看作是自己没下载完的文件了,续载的时候先检查下已存在的同名文件是否是自己以前下载过的文件这种情况就可以避免了。 想到那里说到那里,难免有错误的地方! 如果自动下载,不需要显示的话,最简单的方法就是用API数: DECLARE INTEGER URLDownloadToFile IN urlmon.dll; INTEGER pCaller, STRING szURL,; STRING szFileName, INTEGER dwReserved,; INTEGER lpfnCB LOCAL cRemoteFile, cLocalFile, nResult cRemoteFile = "; &&文件静态地址 cLocalFile = "123.gif" &&本地文件名 WAIT WINDOW NOWAIT "Downloading file..." nResult = URLDownloadToFile(0, cRemoteFile, cLocalFile, 0,0) WAIT CLEAR IF nResult = 0 ? "下载成功~" ELSE ? "下载出错,出错代码:", nResult ENDIF 效果如图: VFP Code: DOWNLAOD.PRG Public _form1 _form1=CreateObject("form1") _form1.show RETURN DEFINE CLASS form1 AS form Top = 90 Left = 294 Height = 183 Width = 343 DoCreate = .T. Caption = "行者示例-文件下载" BackColor =RGB( 153,153,153) Name = "form1" PROCEDURE down X=ALLTRIM(STR(PD*102400)) IF X=='' X='0' endi Y=ALLTRIM(STR((PD+1)*102400-1)) f_Header='Range: bytes='+X+'-'+Y IF PD>f_cs f_header='Range: bytes='+X+'-' thisform.inet2.execute(f_url,'get',,f_Header) ELSE thisform.inet2.execute(f_url,'get',,f_header) ENDIF ENDPROC PROCEDURE Init this.AddObject("Dataenvironment","_classname1") this.AddObject("Inet1","_classname2") this.AddObject("Command3","_classname3") this.AddObject("inet2","_classname4") this.AddObject("Label2","_classname5") this.AddObject("Shape1","_classname6") this.AddObject("Shape2","_classname7") this.AddObject("Shape3","_classname8") this.AddObject("Label5","_classname9") this.AddObject("Label6","_classname10") this.AddObject("Label1","_classname11") this.AddObject("Label3","_classname12") this.AddObject("Label4","_classname13") this.AddObject("Timer1","_classname14") PUBLIC f_url,f_size,f_cs,f_sy,f_name,PD,h,f_header,X,Y,JS thisform.shape3.Width=0 ENDPROC ENDDEFINE DEFINE CLASS _classname1 AS dataenvironment Visible=.T. Top = 0 Left = 0 Width = 0 Height = 0 DataSource = .NULL. Name = "Dataenvironment" ENDDEFINE DEFINE CLASS _classname2 AS olecontrol Visible=.T. Comment = "" Top = 15 Left = 127 Height = 24 Width = 38 Name = "Inet1" oleclass="InetCtls.Inet.1" PROCEDURE StateChanged *** ActiveX 控件事件 *** LPARAMETERS state DO case CASE state=1 thisform.label1.caption='下载状态:正在连接服务器下载地址.....' *!* CASE state=2 *!* thisform.label1.caption='连接服务器成功' *!* CASE state=3 *!* thisform.label1.caption='该控件正在与主机连接。 ' *!* CASE state=4 *!* thisform.label1.caption='该控件已与主机连接成功。' *!* CASE state=5 *!* thisform.label1.caption='该控件正在向主机发送请求。' *!* CASE state=6 *!* thisform.label1.caption='该控件发送请求已成功。' *!* CASE state=7 *!* thisform.label1.caption='该控件正在接收主机的响应。 ' *!* CASE state=8 *!* thisform.label1.caption='该控件已成功地接收到主机的响应。 ' *!* CASE state=9 *!* thisform.label1.caption='该控件正在解除与主机的连接。' *!* CASE state=10 *!* thisform.label1.caption='该控件已成功地与主机解除了连接。 ' CASE state=11 thisform.label1.caption='下载状态:与主机通讯时出现了错误!' CASE state=12 thisform.label1.caption='下载状态:正在下载该文件.....' f_size=VAL(thisform.inet1.getheader('Content-Length')) thisform.label2.Caption='文件大小:'+ALLTRIM(STR(f_size))+' byte' f_cs=INT(f_size/102400) f_sy=MOD(f_size,102400) h=FCREATE(f_name) thisform.timer1.Interval=1000 PD=0 thisform.down() thisform.inet1.object.Cancel endc ENDPROC ENDDEFINE DEFINE CLASS _classname3 AS commandbutton Visible=.T. Top = 140 Left = 150 Height = 25 Width = 60 Caption = "开始下载" Name = "Command3" PROCEDURE Click f_url=''&&被下载文件地址 f_name='ad.zip'&&被存放到本地的文件名 thisform.shape3.Width=0 JS=0&&下载秒数计数 thisform.inet1.execute(f_url) ENDPROC ENDDEFINE DEFINE CLASS _classname4 AS olecontrol Visible=.T. Comment = "" Top = 15 Left = 178 Height = 24 Width = 38 Name = "inet2" oleclass="InetCtls.Inet.1" PROCEDURE StateChanged *** ActiveX 控件事件 *** LPARAMETERS state IF state=12 IF PD>=f_cs st=thisform.inet2.GetChunk(f_sy,1) =FWRITE(h,st) =FCLOSE(h) thisform.timer1.Interval=0 thisform.label6.Caption='100%' thisform.Caption='文件下载完毕' thisform.label1.caption='下载状态:' thisform.label2.caption='下载状态:' =MESSAGEBOX('下载完毕') *!* thisform.inet1.object.Cancel else st=thisform.inet2.GetChunk(102400,1) PD=PD+1 =FWRITE(h,st) thisform.shape3.Width=(PD/f_cs)*246 thisform.down() endi endi ENDPROC ENDDEFINE DEFINE CLASS _classname5 AS label Visible=.T. AutoSize = .T. FontSize = 11 BackStyle = 0 Caption = "文件大小:" Height = 19 HelpContextID = 1 Left = 7 Top = 31 Width = 77 Name = "Label2" ENDDEFINE DEFINE CLASS _classname6 AS shape Visible=.T. Top = 105 Left = 76 Height = 17 Width = 248 BackStyle = 0 Curvature = 10 Name = "Shape1" ENDDEFINE DEFINE CLASS _classname7 AS shape Visible=.T. Top = 104 Left = 75 Height = 17 Width = 248 BackStyle = 0 Curvature = 10 BorderColor =RGB( 255,255,255) Name = "Shape2" ENDDEFINE DEFINE CLASS _classname8 AS shape Visible=.T. Top = 106 Left = 77 Height = 15 Width = 246 BackStyle = 1 BorderStyle = 0 BorderWidth = 0 Curvature = 10 BackColor =RGB( 128,128,128) Name = "Shape3" ENDDEFINE DEFINE CLASS _classname9 AS label Visible=.T. AutoSize = .T. FontSize = 11 BackStyle = 0 Caption = "下载进度:" Height = 19 Left = 7 Top = 105 Width = 77 Name = "Label5" ENDDEFINE DEFINE CLASS _classname10 AS label Visible=.T. AutoSize = .T. BackStyle = 0 Caption = "%" Height = 16 Left = 204 Top = 106 Width = 8 Name = "Label6" ENDDEFINE DEFINE CLASS _classname11 AS label Visible=.T. AutoSize = .T. FontSize = 11 BackStyle = 0 Caption = "下载状态:" Height = 19 Left = 7 Top = 7 Width = 77 Name = "Label1" ENDDEFINE DEFINE CLASS _classname12 AS label Visible=.T. AutoSize = .T. FontSize = 11 BackStyle = 0 Caption = "下载速率:" Height = 19 Left = 7 Top = 56 Width = 77 Name = "Label3" ENDDEFINE DEFINE CLASS _classname13 AS label Visible=.T. AutoSize = .T. FontSize = 11 BackStyle = 0 Caption = "剩余时间:" Height = 19 Left = 7 Top = 80 Width = 77 Name = "Label4" ENDDEFINE DEFINE CLASS _classname14 AS timer Visible=.T. Top = 27 Left = 231 Height = 23 Width = 23 Interval = 0 Name = "Timer1" PROCEDURE Timer JS=JS+1 sl=ALLTRIM(STR(PD*102400/1024/JS,6,2)) thisform.label3.caption='下载速率:'+sl+' KB/S' thisform.label4.Caption='剩余时间:'+ALLTRIM(STR((f_size-PD*102400)/102 4/VAL(sl)))+' 秒' thisform.label6.Caption=ALLTRIM(STR((PD*102400/f_size)*100,5,2))+'%' thisform.Caption='行者示例-文件下载 '+ALLTRIM(STR((PD*102400/f_size) *100,5,2))+'%' ENDPROC ENDDEFINE
/
本文档为【VFP实现HTTP带进度条的断点下载】,请使用软件OFFICE或WPS软件打开。作品中的文字与图均可以修改和编辑, 图片更改请在作品中右键图片并更换,文字修改请直接点击文字进行修改,也可以新增和删除文档中的内容。
[版权声明] 本站所有资料为用户分享产生,若发现您的权利被侵害,请联系客服邮件isharekefu@iask.cn,我们尽快处理。 本作品所展示的图片、画像、字体、音乐的版权可能需版权方额外授权,请谨慎使用。 网站提供的党政主题相关内容(国旗、国徽、党徽..)目的在于配合国家政策宣传,仅限个人学习分享使用,禁止用于任何广告和商用目的。

历史搜索

    清空历史搜索