设为首页 收藏本站
查看: 1121|回复: 0

[经验分享] ftp和http断点续传及下载delphi实现

[复制链接]

尚未签到

发表于 2016-6-10 10:42:48 | 显示全部楼层 |阅读模式
  接下来我们来写最主要的代码,也就是下载部分了,首先来看HTTP协议的:
procedureTForm1.HttpDownLoad(aURL,aFile:string;bResume:Boolean);
var
tStream:TFileStream;
begin//Http方式下载
ifFileExists(aFile)then//如果文件已经存在
tStream:=TFileStream.Create(aFile,fmOpenWrite)else
tStream:=TFileStream.Create(aFile,fmCreate);

ifbResumethen//续传方式
begin
IdHTTP1.Request.ContentRangeStart:=tStream.Size-1;
tStream.Position:=tStream.Size-1;//移动到最后继续下载
IdHTTP1.Head(aURL);
IdHTTP1.Request.ContentRangeEnd:=IdHTTP1.Response.ContentLength;
endelse//覆盖或新建方式
begin
IdHTTP1.Request.ContentRangeStart:=0;
end;


try
IdHTTP1.Get(aURL,tStream);//开始下载
finally
tStream.Free;
end;
end;
这里我们同样使用IdHTTP的Get过程,函数的aURL是网址,aFile是保存的文件名,bResume确定是否续传,需要注意的就是续传方式时的代码:
IdHTTP1.Request.ContentRangeStart:=tStream.Size-1;
tStream.Position:=tStream.Size-1;//移动到最后继续下载
IdHTTP1.Head(aURL);
IdHTTP1.Request.ContentRangeEnd:=IdHTTP1.Response.ContentLength;
第一行我们将下载开始位置设置为读入文件流的末尾,也就是设置为已经下载了的那部分文件的大小,第二行我们将文件流本身也指向自己的末尾,第三行我们通过Head过程得到网址头信息,在第四行将头信息的文件总大小赋值给下载的结束的位置,至于这里为什么第一行和第二行代码最后都要-1,我当时没有加-1的时候在续下载一个完整的已经下载的文件的时候总是提示错误,最后跟踪IdHTTP的代码发现他在处理下载范围的时候如果开始的位置和结束位置一样时会引发将浮点数转为整数的错误,因而这里加上-1防止这种错误发生,另外一种处理方法就是比较如果开始位置等于结束位置就退出也是可以的。
再来看FTP协议的下载过程:
procedureTForm1.FtpDownLoad(aURL,aFile:string;bResume:Boolean);
var
tStream:TFileStream;
sName,sPass,sHost,sPort,sDir:string;
begin//ftp方式下载
ifFileExists(aFile)then//建立文件流
tStream:=TFileStream.Create(aFile,fmOpenWrite)else
tStream:=TFileStream.Create(aFile,fmCreate);

GetFTPParams(aURL,sName,sPass,sHost,sPort,sDir);
withIdFTP1do
try
ifConnectedthenDisconnect;//重新连接
Username:=sName;
Password:=sPass;
Host:=sHost;
Port:=StrToInt(sPort);
Connect;
except
exit;
end;

IdFTP1.ChangeDir(sDir);//改变目录
BytesToTransfer:=IdFTP1.Size(aFile);
try
ifbResumethen//续传
begin
tStream.Position:=tStream.Size;
IdFTP1.Get(aFile,tStream,True);
endelse
begin
IdFTP1.Get(aFile,tStream,False);
end;
finally
tStream.Free;
end;
end;
这个过程中我们就用到了GetFTPParams()函数将网址的用户名、密码、主机地址、端口、路径等信息分离出来,IdFTP利用这些信息登陆服务器并到相应目录,最后利用Get()过程就很容易实现下载了,它的续传就比HTTP协议要简单很多,因为IdFTP的Get()本身就支持续传。
这里我简单穿插一点的内容,一个服务器是否支持断点续传,我们可以通过发送"REST1"FTP指令来检测,如果返回350则表示支持。
最后我们根据网址来确定使用什么协议来下载:
functionTForm1.GetProt(aURL:string):Byte;
begin//检测下载的地址是http还是ftp
Result:=0;
ifPos('http',LowerCase(aURL))=1then
Result:=1;//http协议
ifPos('ftp',LowerCase(aURL))=1then
Result:=2;//ftp协议
end;
这个函数根据网址返回整数供我们使用。
procedureTForm1.MyDownLoad(aURL,aFile:string;bResume:Boolean);
begin
caseGetProt(aURL)of
0:ShowMessage('不可识别的地址!');
1:HttpDownLoad(aURL,aFile,bResume);
2:FtpDownLoad(aURL,aFile,bResume);
end;
end;
这个过程就利用GetProt()函数返回的整数执行相应的协议下载过程。
(2)接下来看看每个按钮的代码,有了上面的函数,按钮的代码就简单多了:
下载按钮:
procedureTForm1.Button1Click(Sender:TObject);
var
aURL,aFile:string;
begin
aURL:=ComboBox1.Text;//下载地址,例如" DSC0000.gif http://www.2ccc.com/update/demo.exe";
aFile:=GetURLFileName(aURL);//得到文件名,例如"demo.exe"
ifFileExists(aFile)then
begin
caseMessageDlg('文件已经存在,是否续传?',mtConfirmation,mbYesNoCancel,0)of
mrYes:MyDownLoad(aURL,aFile,True);//续传
mrNo:MyDownLoad(aURL,aFile,False);//覆盖
mrCancel:Exit;//取消
end;
endelseMyDownLoad(aURL,aFile,False);//建立新文件下载
end;
MessageDlg()函数弹出一个对话框让用户选择续传、覆盖还是取消下载。
中断按钮:
procedureTForm1.Button2Click(Sender:TObject);
begin
AbortTransfer:=True;
end;
前面忘了介绍,所以这里大家看不明白,AbortTransfer是我们定义的一个私有变量,在开始下载的时候将它设为False,下载的过程中随时监测这个变量,一旦变为True就利用IdHTTP的Disconnect和IdFTP1的Abort方法中断下载,如果没有下载完就中断,那程序的目录中就会有一个下载不完整的程序或者其他东西,下次再下载的时候我们就可以选择续传来完成剩下的下载过程。
procedureTForm1.IdHTTP1WorkBegin(Sender:TObject;AWorkMode:TWorkMode;
constAWorkCountMax:Integer);
begin
AbortTransfer:=False;
……
end;
在IdHTTP1和IdFTP的OnWorkBegin事件我们就将AbortTransfer设置为False了,在他们的Work事件中,我们检测AbortTransfer变量来完成是否中断的操作。
procedureTForm1.IdHTTP1Work(Sender:TObject;AWorkMode:TWorkMode;
constAWorkCount:Integer);
begin
ifAbortTransferthen
begin//中断下载
IdHTTP1.Disconnect;
IdFTP1.Abort;
end;
ProgressBar1.Position:=AWorkCount;
Application.ProcessMessages;
end;
(3)最后是连接状态等信息的代码:
在IdHTTP和IdFTP的OnStatus事件写入:
procedureTForm1.IdHTTP1Status(ASender:TObject;constAStatus:TIdStatus;
constAStatusText:string);
begin
ListBox1.ItemIndex:=ListBox1.Items.Add(AStatusText);
end;
因为IdHTTP和IdFTP在OnWork、OnStatus等事件上执行的代码都是一样的,所以我们只用写其中一个的代码,然后另外一个选择相同的事件就OK了。

图8.3.4
3.全部代码写完收工,F9运行一下看看效果,是不是能断点续传。
【程序小结】
本程序主要的功能由IdHTTP和IdFTP组件完成,主要掌握他们的Get过程实现断点续传的方法以及字符串的分析分解方法,这里我们同样使用了流格式,不过这次不是内存流而是文件流。通过本例,读者应该初步掌握调试程序时断点的使用,事件代码的共用等。
【作者后话】
在写完这篇文章不久,作者偶然间察看了Indy系列组件的帮助,发现一个封装了分析URL结构的类TIdURI,在IdURI单元,这个类可以很轻松的将我们上面的GetFTPParams()函数的功能实现,例如:
var
URI:TIdURI;
begin
URI:=TIdURI.Create(aURL);//建立
try
sProtocol:=URI.Protocol;//协议
sHost:=URI.Host;//主机
//……等等都可以通过URI的属性得到
finally
URI.Free;
end;
end;
使用此类我们的程序可以变得更简单,如何修改就留给读者自己去完善吧

运维网声明 1、欢迎大家加入本站运维交流群:群②:261659950 群⑤:202807635 群⑦870801961 群⑧679858003
2、本站所有主题由该帖子作者发表,该帖子作者与运维网享有帖子相关版权
3、所有作品的著作权均归原作者享有,请您和我们一样尊重他人的著作权等合法权益。如果您对作品感到满意,请购买正版
4、禁止制作、复制、发布和传播具有反动、淫秽、色情、暴力、凶杀等内容的信息,一经发现立即删除。若您因此触犯法律,一切后果自负,我们对此不承担任何责任
5、所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其内容的准确性、可靠性、正当性、安全性、合法性等负责,亦不承担任何法律责任
6、所有作品仅供您个人学习、研究或欣赏,不得用于商业或者其他用途,否则,一切后果均由您自己承担,我们对此不承担任何法律责任
7、如涉及侵犯版权等问题,请您及时通知我们,我们将立即采取措施予以解决
8、联系人Email:admin@iyunv.com 网址:www.yunweiku.com

所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其承担任何法律责任,如涉及侵犯版权等问题,请您及时通知我们,我们将立即处理,联系人Email:kefu@iyunv.com,QQ:1061981298 本贴地址:https://www.yunweiku.com/thread-228559-1-1.html 上篇帖子: java 实现ftp上传与下载文件夹 下篇帖子: Vuln: IBM AIX FTP Server 'NLST' Command Information Disclosure Vulnerability
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

扫码加入运维网微信交流群X

扫码加入运维网微信交流群

扫描二维码加入运维网微信交流群,最新一手资源尽在官方微信交流群!快快加入我们吧...

扫描微信二维码查看详情

客服E-mail:kefu@iyunv.com 客服QQ:1061981298


QQ群⑦:运维网交流群⑦ QQ群⑧:运维网交流群⑧ k8s群:运维网kubernetes交流群


提醒:禁止发布任何违反国家法律、法规的言论与图片等内容;本站内容均来自个人观点与网络等信息,非本站认同之观点.


本站大部分资源是网友从网上搜集分享而来,其版权均归原作者及其网站所有,我们尊重他人的合法权益,如有内容侵犯您的合法权益,请及时与我们联系进行核实删除!



合作伙伴: 青云cloud

快速回复 返回顶部 返回列表