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

delphi 用Indy实现FTP客户端

[复制链接]

尚未签到

发表于 2015-5-26 11:05:12 | 显示全部楼层 |阅读模式
delphi 用Indy实现FTP客户端

  2009-08-21 18:33:07|  分类: Delphi 编程 |  标签: |字号大中小 订阅
  讲这个课题的原因,是因为正好我在看“DELPHI 组件经典解析”这本书,里面重点提到的是INDY 9.0 控件的使用。
  首先大家了解一下FTP的基本知识:FTP是一个标准协议,它是在计算机和网络之间交换文件的最简单的方法。
  FTP也是应用TCP/IP协议的应用协议标准。
  FTP通常于将作者的文件上传至服务器,或从服务器上下传文件的一种普遍的使用方式作为用户,您可以用非常简单的DOS界面来使用FTP,也可以使用由第三方提供的软件(如FLASHFXP)来对服务器的数据进行删除,重命名等操作。  
  当然,使用这些之前,必须先要登录服务器,用指定的用户名和密码或匿名(Anonymous)登录。   
  这些大家都知道,不过还是讲一下。用DOS操作FTP我不讲了。我今天主要用INDY组件里的IDFTP控件做一FTP客户端软件(非常简单 )  
  了  
  我现在讲一下IDFTP控件的几个属性如下:  
  Host:FTP服务器地址。
  USER:用户帐号。
  Password:密码。
  Passive:用于控制FTP数据连接方法。FTP的数据传输可以有主动和被动。
  PORT是主动模式,在建立数据通道时,服务端去连接别人;
  PASV是被动模式,在建立数据通道时,服务端被别人连接;
  建立数据通道时,用PORT模式还是PASV模式,选择权在于FTP客户端。
  IDFTP里的passive是一个Boolean数据类型。当True时为主动;当false时为被动。
  Port:FTP服务的默认端口是21。
  TransferType:传输文件的类型,可以取值为FtBinary(8位的任意文件)和FtAscii(7位的文本文件)。
  SystemDesc:FTP服务器的描述。   
  IDFTP的几个方法
  常用的方法有以下几个:
  Connect:连接FTP服务器.
  Abort:停止FTP服务的操作。
  Quit:关闭客户端与服务器的连接.
  Noop:用于保持连接的命令,防止被服务器关掉连接.
  List:获取FTP服务器上的文件和目录列表.
  原型为
  procedure List(ADest:TStrings;Const ASpecifier:String;const ADetails:Boolean);
  RetrieveCurrentDir:取得当前目录的名称.
  Site:发送FTP服务器的命令.
  原型为:
  procedure Site(const ACommand:string);
  ChangeDir:改变FTP服务器上的当前目录
  原型为: procedure ChangeDir(const ADirName:string);
  ChangeDirUp:将FTP服务器上的目录返回到你目录.  
  温州-Dillon(86695893) 13:08:26
  MakeDir:在服务器上建立一个新目录.
  原型为:
  procedure MakeDir(const ADirName:String);
  RemoveDir:删除服务器上的一个目录.
  原型为:
  procedure RemoveDir(const ADirName:string);
  Get:从FTP服务器上下载文件.这个方法被重载了.
  原型为:
  procedure Get(const ASourceFile:string;ADest:TStream);overload;
  procedure Get(const ASourceFile:string;const ADest:string;ACanOverWrite:Boolean);overload;
  Put:用于向服务器上传文件.该方法被重载.
  原型为:
  procedure Put(const ASourceFile:TStream;const ADest:string;const Appand:Boolean);overload;
  procedure Put(const ASourceFile:string;const ADest:string;const AAppand:Boolean);overload;
  KillDataChannal:关闭FTP数据通道.
  所谓“重载”,就是当从多个“类”身上继承一些方法时,会发生冲突。为了避免这一个冲突,就使用了“重载”功能  
  Delete:删除FTP服务器上一个文件.
  原形为:procedure Delete(const AfileName:string);
  Rename:更改服务器上的文件名.
  原型为:
  procedure Rename(const ASourceFile:string;const ADestFile:string);
  Size:获取文件大小信息.
  原型为:
  function Size(const AFileName:string):Integer;   
  当大家装好INDY9.0 附带一个例程,在INDY\FTPDEMO下可以找到.  
  是一个不错的DEMO  
  我仿造这个DEMO做的一个例子。里面包含详细的注释。
  当然,还要讲一下,做FTP客户端的心得哦  
  我现在,慢慢把里面的代码发了来做一下讲解  
  首先是登录按钮里的代码:  
  还是先给大家看一下这个界面吧  
  Delete:删除FTP服务器上一个文件.
  原形为:procedure Delete(const AfileName:string);
  Rename:更改服务器上的文件名.
  原型为:
  procedure Rename(const ASourceFile:string;const ADestFile:string);
  Size:获取文件大小信息.
  原型为:
  function Size(const AFileName:string):Integer;
  begin
  ftpcon.Enabled:=false;
  //-----------------连接FTP服务器------------------//
  with idftp do
  begin
  try
  Host:=trim(edit1.Text);       //FTP服务器IP地址
  Username:=trim(edit2.Text); //用户名
  Password:=trim(edit3.Text); //密码
  Connect;    // 连接
  DirectoryListBox.Items.Clear;    // 清空目录以及文件信息
  DebugListBox.Items.Clear;    // 清空记录信息
  // SaveFTPHostInfo(trim(CURDIR.Text), 'FTPHOST');
  finally
  if Connected then
  begin
  DisplayDir(trim(CURDIR.Text)); // 改变当前路径
  FTPCon.Enabled:=false;     // 连接按钮
  FTPDisCon.Enabled:=True; // 断开按钮
  end;
  end;
  end;
  end;  
  断开按钮的代码:  
  begin
  try
  if IdFTP.Connected then     // 判断客户端是否连着服务器
  IdFTP.Abort;
  if TransferrignData then    // 判断客户端与服务器之间是否有数据传输
  IdFTP.Quit;
  finally
  IdFTP.Disconnect;    // 断开连接
  FTPCon.Enabled:=true;
  FTPDisCon.Enabled:=false;
  end;
  end;  
  TransferrignData变量全局变量里有定义的  
  连接按钮里的DisplayDir的过程如下:   
  procedure TFFTPClient.DisplayDir(DirName: String);
  Var
  LS: TStringList;
  begin
  LS := TStringList.Create;
  try
  IdFTP.ChangeDir(DirName);
  IdFTP.TransferType:=ftASCII;    // 编译不通过时 USES IdFTPCommon
  CURDIR.Text:= IdFTP.RetrieveCurrentDir;
  DirectoryListBox.Items.Clear;
  IdFTP.List(LS);    // 把IDFTP里的LIST与LS关联起来
  DirectoryListBox.Items.Assign(LS);     // 把DIRECTORYLISTBOX 与 LS 关联起来
  if DirectoryListBox.Items.Count > 0 then
  if AnsiPos('total', DirectoryListBox.Items[0]) > 0 then DirectoryListBox.Items.Delete(0);
  finally
  LS.Free;
  end;
  end;  
  还有一个最重要的一段代码,就是listbox如何显示目录信息的  
  首先,把LISTBOX的STYLE的属性改成lbOwnerDrawFixed  
  再在ONDRAWITEM方法里添加如下代码:  
  procedure TFFTPClient.DirectoryListBoxDrawItem(Control: TWinControl;
  Index: Integer; Rect: TRect; State: TOwnerDrawState);
  Var
  R: TRect;
  begin
  //---------------------------------当选择一条记录时
  if odSelected in State then
  begin   
  DirectoryListBox.Canvas.Brush.Color := $00895F0A;
  DirectoryListBox.Canvas.Font.Color := clWhite;
  end
  else
  begin
  DirectoryListBox.Canvas.Brush.Color := clWindow;
  end;
  //---------------------------------显示当前目录里的信息
  if Assigned(IdFTP.DirectoryListing) and (IdFTP.DirectoryListing.Count>Index) then
  begin
  DirectoryListBox.Canvas.FillRect(Rect);
  with IdFTP.DirectoryListing.Items[Index] do
  begin
  //------------------------//
  DirectoryListBox.Canvas.TextOut(Rect.Left, Rect.Top, FileName); // 文件名
  R := Rect;
  R.Left := Rect.Left + HeaderControl1.Sections.Items[0].Width;
  //------------------------//
  R.Right := R.Left + HeaderControl1.Sections.Items[1].Width;
  DirectoryListBox.Canvas.FillRect(R);
  DirectoryListBox.Canvas.TextOut(R.Left, Rect.Top, IntToStr(Size)); // 文件大小
  //------------------------//
  R.Left := R.Right;
  R.Right := R.Left + HeaderControl1.Sections.Items[2].Width;
  DirectoryListBox.Canvas.FillRect(R);
  if ItemType = ditDirectory then     // 是文件夹类型    编译不通过时要USES IDFTPLIST
  begin
  DirectoryListBox.Canvas.TextOut(R.Left, Rect.Top, '文件夹');
  end
  else
  begin
  DirectoryListBox.Canvas.TextOut(R.Left, Rect.Top, '文件');
  end;
  //------------------------//
  R.Left := R.Right;
  R.Right := R.Left + HeaderControl1.Sections.Items[3].Width;
  DirectoryListBox.Canvas.FillRect(R);
  DirectoryListBox.Canvas.TextOut(R.Left, Rect.Top, FormatDateTime('yyyy-mm-dd hh:mm', ModifiedDate)); // 修改时间
  //------------------------//
  R.Left := R.Right;
  R.Right := R.Left + HeaderControl1.Sections.Items[4].Width;
  DirectoryListBox.Canvas.FillRect(R);
  DirectoryListBox.Canvas.TextOut(R.Left, Rect.Top, GroupName); // 组名
  //------------------------//
  R.Left := R.Right;
  R.Right := R.Left + HeaderControl1.Sections.Items[5].Width;
  DirectoryListBox.Canvas.FillRect(R);
  DirectoryListBox.Canvas.TextOut(R.Left, Rect.Top, OwnerName);    // 拥有者名字
  //------------------------//
  R.Left := R.Right;
  R.Right := R.Left + HeaderControl1.Sections.Items[6].Width;
  DirectoryListBox.Canvas.FillRect(R);
  DirectoryListBox.Canvas.TextOut(R.Left, Rect.Top, OwnerPermissions + GroupPermissions + UserPermissions);    // 权限
  end;
  end;
  end;  
  这几部分是这软件里的中心  
  不过,可以通过IDFTP里的work,status,workbegin,workend来实现进度条  
  还有上传代码:  
  if IdFTP.Connected then
  begin
  if OpenDialog1.Execute then
  try
  IdFTP.TransferType := ftBinary;
  IdFTP.Put(OpenDialog1.FileName, ExtractFileName(OpenDialog1.FileName));
  finally
  DisplayDir(idftp.RetrieveCurrentDir);
  end;
  end;
  end;  
  这段代码,首先要判断IDFTP是否还连着  
  下传代码如下:  
  温州-Dillon(86695893) 13:36:23
  procedure TFFTPClient.DirectoryListBoxDblClick(Sender: TObject);
  Var
  FName: String;
  begin
  if not IdFTP.Connected then // 判断FTP是否还连着服务器
  exit;
  FName := IdFTP.DirectoryListing.Items[DirectoryListBox.ItemIndex].FileName;
  if IdFTP.DirectoryListing.Items[DirectoryListBox.ItemIndex].ItemType = ditDirectory then // 假如双击是文件夹,就改变路径
  begin
  CURDIR.Text:=Trim(FName);
  DisplayDir(CURDIR.Text);
  end
  else
  begin
  try
  SaveDialog1.FileName := Name; // 得到保存的文件名
  if SaveDialog1.Execute then
  begin
  IdFTP.TransferType := ftBinary; // 以二进制进行传输
  BytesToTransfer := IdFTP.Size(Name); // 得到文件的大小
  if FileExists(Name) then
  begin
  case MessageDlg('文件已经存在,是否重新下载?',mtConfirmation, mbYesNoCancel, 0) of
  mrYes:
  begin
  BytesToTransfer := BytesToTransfer-FileSizeByName(Name); // FileSizeByName在IdGlobal
  IdFTP.Get(Name, SaveDialog1.FileName, false, true);
  end;
  mrNo:
  begin
  IdFTP.Get(Name, SaveDialog1.FileName, true);
  end;
  mrCancel:
  begin
  exit;
  end;
  end;
  end
  else
  begin
  IdFTP.Get(Name, SaveDialog1.FileName, false);
  end;
  end;
  finally
  end;
  end;
  end;  
  我要直接做在目录列表框的双击方法里的,假如双击文件就下载,文件夹就打开  
  其它的功能,都是通过IDFTP的方法直接实现的。例如新建目录:  
  var
  DirName:string;
  begin
  DirName:=InputBox('输入新目录名称', '提示信息', '');
  if DirName  '' then
  try
  IdFTP.MakeDir(DirName);
  DisplayDir(CURDIR.Text);
  finally
  end;
  end;  
  所以,对于FTP客户端的讲解也就如些了。  
  是啊,把所有代码都压缩传到共享里    noop只是客户端连到服务器,不被服务端T了

运维网声明 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-70845-1-1.html 上篇帖子: 【收藏】常用的ftp命令 下篇帖子: JAVA 访问FTP服务器示例(1)
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

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

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

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

扫描微信二维码查看详情

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


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


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


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



合作伙伴: 青云cloud

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