利用Indy的TIdFtp控件实现FTP协议

procedure TForm1.FtpDownLoad(aURL, aFile: string; bResume: Boolean);
var
   tStream: TFileStream;
   sName, sPass, sHost, sPort, sDir: string;
begin //ftp方式下载
   if FileExists(aFile) then //建立文件流
     tStream := TFileStream.Create(aFile, fmOpenWrite) else
     tStream := TFileStream.Create(aFile, fmCreate);

   GetFTPParams(aURL, sName, sPass, sHost, sPort, sDir);
   with IdFTP1 do
   try
     if Connected then Disconnect; //重新连接
     Username := sName;
     Password := sPass;
     Host := sHost;
     Port := StrToInt(sPort);
     Connect;
   except
     exit;
   end;

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

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值