只属于我们的秘密 發表於 2020-5-11 15:41:00

Delphi IdFTP[2] 常用过程、事件、方法介绍

<p><strong><span style="font-size: 16px">Delphi IdFTP 常用过程、事件、方法介绍</span></strong></p>
<p><span style="font-size: 16px"><strong>1、属性</strong></span></p>
<ul>
<li><span style="font-size: 16px"> 默认属性即可,与服务器连接直接相关的属性如主机名与用户等在建立连接时进行设定。需要设定的是RecvBufferSize和SendBufferSize两属性的值。另外需要根据要传输的文件类型指定TransferType属性,而其他属性按默认值设定即可。</span></li>
<li><span style="font-size: 16px"> RecvBufferSize说明(默认值为8192字节):该属性为整型变量,用于指定连接所用的接受缓冲区大小。</span></li>
<li><span style="font-size: 16px"> SendBufferSize说明(默认值为32768字节):该属性也为整型变量,用于指定连接所用的发送缓冲区的最大值。该属性在WriteStream方法中时,可用于TStream指定要发送内容的块数。如果要发送的内容大于本属性值,则发送内容被分为多个块发送。</span></li>
<li><span style="font-size: 16px">TransferType说明(默认值为ftBinary):该属性为TIdFTPTransferType型变量。用于指定传输内容是二进制文件(ftBinary )还是ASCII文件(ftASCII)。应用程序需要使用二进制方式传输可执行文件、压缩文件和多媒体文件等;而使用ASCII方式传输文本或超文本等文本型数据。</span></li>
</ul>
<p><span style="font-size: 16px"><strong>2、事件</strong></span></p>
<ul>
<li><span style="font-size: 16px"> OnDisconnected响应:TNotifyEvent类,用于响应断开(disconnect)事件。当Disconnect方法被调用用来关闭Socket的时候,触发该响应。应用程序必须指定该事件响应的过程,以便对该断开事件进行相应。</span></li>
<li><span style="font-size: 16px"> OnStatus响应:TIdStatusEvent类。该响应在当前连接的状态变化时被触发。该事件可由DoStatus方法触发并提供给事件控制器属性。axStatus是当前连接的TIdStatus值;aaArgs是一个可选的参数用于格式化函数,它将用于构造表现当前连接状态的文本消息。</span></li>
<li><span style="font-size: 16px"> OnWork响应:OnWord是TWorkEvent类事件的响应控制器。OnWork用于关联DoWork方法当缓冲区读写操作被调用时通知Indy组件和类。它一般被用于控制进度条和视窗元素的更新。AWorkMode表示当前操作的模式,其中:wmRead-组件正在读取数据;wmWrite-组件正在发送数据。AWorkCount指示当前操作的字节计数。</span></li>
<li><span style="font-size: 16px"> OnWorkBegin响应:TWorkBeginEvent类。当缓冲区读写操作初始化时,该事件关联BeginWork方法用于通知Indy组件和类。它一般被用于控制进度条和视窗元素的更新。AWorkMode表示当前操作的模式,其中:wmRead-组件正在读取数据;wmWrite-组件正在发送数据。AWorkCountMax用于指示发送到OnWorkBegin事件的操作的最大字节数,0值代表未知。</span></li>
<li><span style="font-size: 16px"> OnWorkEnd响应:TWorkEndEvent类。当缓冲区读写操作终止时,该事件关联EndWork方法用于通知Indy组件和类。AWorkMode表示当前操作的模式,其中:wmRead-组件正在读取数据;wmWrite-组件正在发送数据。AWorkCount表示操作的字节数。</span></li>
<li><span style="font-size: 16px">在事件响应中,主要通过上述五种事件响应来控制程序。在一般情况下,在OnDisconnected中设定连接断开的界面通知;在OnStatus中设定当前操作的状态;在OnWork中实现传输中状态条和其他参数的显示;而在OnWorkBegin和OnWorkEnd中分别设定开始传输和传输结束时的界面。</span></li>
</ul>
<p><span style="font-size: 16px"><strong>3、过程、方法(Connext、<strong>ChangeDir、<strong>List、Get、Put</strong></strong>)</strong></span></p>
<p><span style="font-size: 16px">3.1 连接</span></p>
<p><span style="font-size: 16px">procedure <strong>Connect</strong>(AAutoLogin: boolean; const ATimeout: Integer);&nbsp; //连接远程FTP服务器</span></p>
<p><span style="font-size: 16px">属性:</span></p>
<ul>
<li><span style="font-size: 16px">AAutoLogin: boolean = True&nbsp; &nbsp;//连接后自动登录,该参数默认为True。</span></li>
<li><span style="font-size: 16px">const ATimeout: Integer = IdTimeoutDefault&nbsp; &nbsp;//超时时间,单位:秒。</span></li>
</ul>
<p><span style="font-size: 16px">示例代码:</span></p>
<div class="cnblogs_Highlighter">
<pre class="brush:delphi;gutter:true;"><span style="font-size: 16px">if IdFTP1.Connected then
try
if TransferrignData then
    IdFTP1.Abort;
IdFTP1.Quit;
finally
end
else
with IdFTP1 do
try
    Username := UserIDEdit.Text;
    Password := PasswordEdit.Text;
    Host := FtpServerEdit.Text;
    Connect;
    ChangeDir(CurrentDirEdit.Text);
finally
end;</span></pre>
</div>
<p><span style="font-size: 16px">3.2 改变目录</span></p>
<p><span style="font-size: 16px">procedure <strong>ChangeDir</strong>(const ADirName: string);&nbsp; &nbsp;//改变工作目录</span></p>
<p><span style="font-size: 16px">属性</span></p>
<ul>
<li><span style="font-size: 16px">const ADirName: string&nbsp; //远程服务器的目录描述&nbsp; &nbsp;说明:该过程实际上是实现了FTP CWD命令。</span></li>
</ul>
<p><span style="font-size: 16px">procedure <strong>ChangeDirUp</strong>;&nbsp; //到上一级目录&nbsp; &nbsp;也可以用 ,IdFTP1.ChangeDir('..'); //返回上一级目录</span></p>
<p><span style="font-size: 16px">function <strong>RetrieveCurrentDir</strong>: string;&nbsp; &nbsp;//该函数返回当前目录名</span></p>
<p>&nbsp;</p>
<p><span style="font-size: 16px">3.3 列表(目录、文件、属性)</span></p>
<p><span style="font-size: 16px">procedure <strong>List</strong>(ADest: TStrings; const ASpecifier: string; const ADetails: boolean);&nbsp; //列出当前目录所有文件和子目录及其属性</span></p>
<p><span style="font-size: 16px">参数:</span></p>
<ul>
<li><span style="font-size: 16px">ADest: TStrings&nbsp; //保存文件及子目录的返回结果</span></li>
<li><span style="font-size: 16px">const ASpecifier: string =&nbsp; //文件掩码,用于列出符合条件的文件</span></li>
<li><span style="font-size: 16px">const ADetails: boolean = true&nbsp; //包含文件和子目录属性 true,返回所有属性(大小、时间、类型等),false 只显示名称</span></li>
</ul>
<p><span style="font-size: 16px">相对属性:</span></p>
<p><span style="font-size: 16px">  property DirectoryListing: TIdFTPListItems;&nbsp; // 返回文件及目录结构的列表</span></p>
<p><span style="font-size: 16px">示例代码:</span></p>
<div class="cnblogs_Highlighter">
<pre class="brush:delphi;gutter:true;"><span style="font-size: 16px">LS := TStringList.Create;
try
IdFTP1.ChangeDir(DirName);
IdFTP1.TransferType := ftASCII;
CurrentDirEdit.Text := IdFTP1.RetrieveCurrentDir;
DirectoryListBox.Items.Clear;
IdFTP1.List(LS);
DirectoryListBox.Items.Assign(LS);
if DirectoryListBox.Items.Count &gt; 0 then
    if AnsiPos(total, DirectoryListBox.Items) &gt; 0 then
      DirectoryListBox.Items.Delete(0);
finally
LS.Free;
end;&nbsp;</span></pre>
</div>
<p><span style="font-size: 16px">也可以这样用(补充 2020.06.16):</span></p>
<div class="cnblogs_Highlighter">
<pre class="brush:delphi;gutter:true;">IdFTP1.List(nil);   //获取当前目录的所有信息
//或者
IdFTP1.List(DirList);   //这个会得到列表的所有信息,包含时间、大小、类型等,相当于 IdFTP1.List(DirList,'',true);
//或者
IdFTP1.List(DirList,'',False);//得到FTP路径下的所有文件夹名称 给到 DirList ,false只获取目录名称,这种方式获取的数据不包含数据类型的判断
//或者
IdFTP1.List;   //支持Delphi XE 版本
//或者
IdFTP1.List('',False);//支持Delphi XE 版本


//看源代码:
procedure TIdFTP.List;
begin
List(nil);
end;

procedure TIdFTP.List(const ASpecifier: string; ADetails: Boolean);
begin
List(nil, ASpecifier, ADetails);
end;

procedure TIdFTP.List(ADest: TStrings; const ASpecifier: string = ''; ADetails: Boolean = True);      {do not localize}
var
LDest: TMemoryStream;
LTrans : TIdFTPTransferType;
begin
if ADetails and UseMLIS and FCanUseMLS then begin
    ExtListDir(ADest, ASpecifier);
    Exit;
end;
// Note that for LIST, it might be best to put the connection in ASCII mode. because some old servers such as TOPS20 might require this.We restore it if the original mode was not ASCII.
 // It's a good idea to do this anyway because some clients still do this such as WS_FTP Pro and Microsoft's FTP Client.
{注意,对于LIST,最好将连接设置为ASCII模式。因为像top20这样的旧服务器可能需要这个。如果原始模式不是ASCII,我们将恢复它。无论如何,这样做是一个好的方式,因为有些客户机仍然这样做,如WS_FTP Pro和微软的FTP客户机。}
LTrans := TransferType;
if LTrans &lt;&gt; ftASCII then begin
    Self.TransferType := ftASCII;
end;
try
    LDest := TMemoryStream.Create;
    try
      InternalGet(Trim(iif(ADetails, 'LIST', 'NLST') + ' ' + ASpecifier), LDest); {do not localize}
      FreeAndNil(FDirectoryListing);
      FDirFormat := '';
      LDest.Position := 0;
      FListResult.Text := ReadStringFromStream(LDest, -1, IOHandler.DefStringEncoding{$IFDEF STRING_IS_ANSI}, IOHandler.DefAnsiEncoding{$ENDIF});
      TIdFTPListResult(FListResult).FDetails := ADetails;
      TIdFTPListResult(FListResult).FUsedMLS := False;
      // FDirFormat will be updated in ParseFTPList...
    finally
      FreeAndNil(LDest);
    end;
    if ADest &lt;&gt; nil then begin
      ADest.Assign(FListResult);
    end;
    DoOnRetrievedDir;
finally
    if LTrans &lt;&gt; ftASCII then begin
      TransferType := LTrans;
    end;
end;
end;
</pre>
</div>
<p>&nbsp;</p>
<p>&nbsp;</p>
<p><span style="font-size: 16px">3.4 下载</span></p>
<p><span style="font-size: 16px">  procedure <strong>Get</strong>(const ASourceFile: string; ADest: TStream; AResume: Boolean); overload;</span></p>
<p><span style="font-size: 16px">  procedure <strong>Get</strong>(const ASourceFile: string; const ADestFile: string; const ACanOverwrite: boolean; AResume: Boolean); overload;&nbsp; //从远程服务器上获取文件。</span></p>
<p><span style="font-size: 16px">属性说明:</span></p>
<ul>
<li><span style="font-size: 16px">const ASourceFile: string&nbsp; //远程服务器上的源文件名,即FTP服务器上的文件名。</span></li>
<li><span style="font-size: 16px">ADest:TStream  //将写入文件数据的流。</span></li>
<li><span style="font-size: 16px">const ADestFile: string&nbsp; //保存到客户机上的文件名 (本地计算机上的文件名和可选路径)</span></li>
<li><span style="font-size: 16px">const ACanOverwrite: boolean = false&nbsp; //重写同名文件 (用相同的名称覆盖现有文件)</span></li>
<li><span style="font-size: 16px">AResume: Boolean = false&nbsp; //是否进行断点续传 (可以完成部分下载)</span></li>
</ul>
<p><span style="font-size: 16px">示例代码:(优化2022.08)</span></p>
<div class="cnblogs_Highlighter">
<pre class="brush:delphi;gutter:true;">SaveDialog1.FileName := Name;
if SaveDialog1.Execute then
begin
SetFunctionButtons(false);
IdFTP1.TransferType := ftBinary;
BytesToTransfer := IdFTP1.Size(Name);
if FileExists(Name) then
begin
    case MessageDlg('File aready exists. Do you want to resume the download operation?', mtConfirmation, mbYesNoCancel, 0) of
      mrYes:
      begin
          BytesToTransfer := BytesToTransfer - FileSizeByName(Name);
          IdFTP1.Get(Name, SaveDialog1.FileName, false, true);
   end;
      mrNo:
      begin
          IdFTP1.Get(Name, SaveDialog1.FileName, true);
      end;
      mrCancel:
      begin
          exit;
      end;
    end;
end
else
begin
    IdFTP1.Get(Name, SaveDialog1.FileName, false);
end;
end;
</pre>
</div>
<p>&nbsp;</p>
<p>  </p>
<p>&nbsp;</p>
<p><span style="font-size: 16px">提示:下载之前,查看 DirectoryListing.Items.ItemType是否为文件,如返回为ditDirectory则代表当前文件名为目录,不能下载,必须导向到文件才可。如为文件,则可以进行下载。在下载前,设定传输的类型为二进制文件,并且指定本地要保存的路径。通过调用Get方法,实现文件的下载。下载过程较慢,可以考虑将其放到线程中实现。</span></p>
<p>&nbsp;</p>
<p><span style="font-size: 16px">其他描述:</span><span style="font-size: 16px">Get是一个重载过程,允许FTP客户端使用FTP RETR命令谓词从FTP服务器检索具有ASourceFile中指定名称的文件。Get的重载实现为来自FTP服务器的数据使用基于文件或流的目的地,如ADestFile或ADest中指定的。</span></p>
<p><span style="font-size: 16px">当AResume为True且CanResume指示FTP服务器实现允许FTP REST命令谓词时,Get允许继续先前的部分下载或将数据附加到本地文件系统上的现有文件。</span></p>
<p><span style="font-size: 16px">在基于文件的方法变体中,当ACanOverwrite为True或文件不存在时,将在检索数据之前创建目标文件。当ACanOverwite为False且AResume为True时,将打开目标文件并将其定位到文件末尾,然后再检索数据。</span></p>
<p><span style="font-size: 16px">当ADestFile中的目标文件已经存在,并且ACanOverwrite和AResume都包含False时,将引发EidftpFileReadyExists异常。</span></p>
<p><span style="font-size: 16px">在Get方法的基于流的变体中,可以在ADest中指定的流中访问从FTP服务器返回的数据。在数据检索期间,Get调用一些方法,这些方法使用被动中指定的连接类型初始化FTP客户端的数据通道。这些受保护的方法还使用ftpTransfer状态值触发OnStatus事件处理程序,从FTP服务器读取流数据,并在完成时使用ftpReady状态值向OnStatus事务处理程序发送信号。如果来自FTP服务器的响应代码是数值225,则可以使用值ftpAborted触发OnStatus matus。</span></p>
<p><span style="font-size: 16px">检索过程完成后,Get使用ADest中指定的流作为参数向OnAfterGet事件处理程序发送信号。</span></p>
<p>&nbsp;</p>
<p>&nbsp;</p>
<p><span style="font-size: 16px">3.5 上传</span></p>
<p><span style="font-size: 16px"> &nbsp;&nbsp; procedure <strong>Put</strong>(const ASource: TStream; const ADestFile: string; const AAppend: boolean); overload;</span></p>
<p><span style="font-size: 16px">  procedure <strong>Put</strong>(const ASourceFile: string; const ADestFile: string; const AAppend: boolean); overload;&nbsp; //上传文件至服务器</span></p>
<p><span style="font-size: 16px">属性:</span></p>
<ul>
<li><span style="font-size: 16px">const ASourceFile: string&nbsp; //将要被上传的文件</span></li>
<li><span style="font-size: 16px">const ADestFile: string =&nbsp; //服务器上的目标文件名</span></li>
<li><span style="font-size: 16px">const AAppend: boolean = false&nbsp; //是否继续上传</span></li>
</ul>
<p><span style="font-size: 16px">代码示例:</span></p>
<div class="cnblogs_Highlighter">
<pre class="brush:delphi;gutter:true;"><span style="font-size: 16px">if IdFTP1.Connected then
begin
if UploadOpenDialog1.Execute then
try
    IdFTP1.TransferType := ftBinary;
    IdFTP1.Put(UploadOpenDialog1.FileName, ExtractFileName(UploadOpenDialog1.FileName));//可以在此添加改变目录的代码;
finally
    //完成清除工作
end;
end;
</span></pre>
</div>
<p><span style="font-size: 16px">&nbsp;</span></p>
<p><span style="font-size: 16px">3.6 删除文件/文件夹</span></p>
<p><span style="font-size: 16px">procedure <strong>Delete</strong>(const AFilename: string);&nbsp; //删除文件</span></p>
<p><span style="font-size: 16px">procedure <strong>RemoveDir</strong>(const ADirName: string);&nbsp; //删除文件夹,根据不同的服务器删除文件夹有不同的要求。有些服务器不允许删除非空文件夹,程序员需要添加清空目录的代码。</span></p>
<p><span style="font-size: 16px">上述过程的参数均为目标名称</span></p>
<p><span style="font-size: 16px">代码示例:</span></p>
<div class="cnblogs_Highlighter">
<pre class="brush:delphi;gutter:true;"><span style="font-size: 16px">if not IdFTP1.Connected then
exit;
Name := IdFTP1.DirectoryListing.Items.FileName;
if IdFTP1.DirectoryListing.Items.ItemType = ditDirectory then
try
idftp1.RemoveDir(Name);
finally
end
else
try
idftp1.Delete(Name);
finally
end;
</span></pre>
</div>
<p><span style="font-size: 16px">  </span></p>
<p>&nbsp;</p>
<p><span style="font-size: 14px; color: rgba(136, 136, 136, 1)">创建时间:2020.05.11  更新时间:2020.06.16、2022.08.05、08.09</span></p>

</div>
<div id="MySignature" role="contentinfo">
    博客园 滔Roy https://www.cnblogs.com/guorongtao 希望内容对你有所帮助,谢谢!<br><br>
来源:https://www.cnblogs.com/guorongtao/p/12869555.html
頁: [1]
查看完整版本: Delphi IdFTP[2] 常用过程、事件、方法介绍