我试图生成一个与某个文件掩码匹配的文件列表,并且Indy因此错误而失败
EidReplyRFCError,带有消息' 。':没有这样的文件或目录。
我尝试了几种变体,这就是结果:
FTP.List( aFiles, '', true );
=>这工作
FTP.List( aFiles, '*.*', false );
=>这也有效
FTP.List( aFiles, '*.*', true );
=>
FTP.List( aFiles, '*.zip', true );
=>这也失败了(尽管它是最新文档中的例子)
FTP.List( '*.*', false );
=>这工作
FTP.List( '*.*', true );
=>
我正在使用Delphi XE5& Indy版本10.6。如果相关,XE8中也存在同样的问题。
也许功能已经改变,文档现在出错了,或者它是Indy中的一个错误?
我需要"详细信息"所以我可以比较时间戳&大小也是。
答案 0 :(得分:11)
这不是TIdFTP
中的错误。这在Indy文档中更多的是遗漏。
EIdReplyRFCError
表示FTP服务器本身报告错误以响应TIdFTP.List()
正在发送的命令。根据{{1}}参数和ADetails
TIdFTP
+ UseMLIS
属性的值,CanUseMLS
可以发送三种不同命令之一:< / p>
List()
因此:
ADetails=False:
NLST [ASpecifier]
ADetails=True:
TIdFTP.UseMLIS=True and TIdFTP.CanUseMLS=True:
MLSD [ASpecifier]
TIdFTP.UseMLIS=False or TIdFTP.CanUseMLS=False:
LIST [ASpecifier]
请注意所有&#34;失败的命令&#34;有一些共同点 - 他们可能正在发送FTP.List( aFiles, '', true ); // this works
// sends either 'LIST' or 'MLSD'
FTP.List( aFiles, '*.*', false ); // this works too
// sends 'NLST *.*'
FTP.List( aFiles, '*.*', true ); // this fails
// sends either 'LIST *.*' or 'MLSD *.*'
FTP.List( aFiles, '*.zip', true ); // this fails too
// sends either 'LIST *.zip' or 'MLSD *.zip'
FTP.List( '*.*', false ); // this works
// sends 'NLST *.*'
FTP.List( '*.*', true ); // this fails
// sends either 'LIST *.*' or 'MLSD *.*'
命令。
每RFC 959,定义MLSD ASpecifier
和LIST
命令:
列表(列表)
此命令使列表从服务器发送到 被动DTP。 如果路径名指定目录或其他目录 一组文件,服务器应该传输一个文件列表 在指定的目录中。如果路径名指定了 文件然后服务器应该发送当前信息 文件。 null参数意味着用户当前正在工作或 默认目录。 ...
姓名单(NLST)
此命令导致从中发送目录列表 服务器到用户站点。 路径名应指定一个 目录或其他特定于系统的文件组描述符;一个 null参数表示当前目录。 ...
Per RFC 3659,定义NLST
命令:
MLST和MLSD命令都允许一个可选参数。 此参数可以是目录名称,也可以是仅限MLST的a 文件名。出于这些目的,一个&#34;文件名&#34;是任何名称 服务器NVFS中的实体不是目录。 TVFS在哪里 支持,任何TVFS相对路径名在当前工作中有效 可以给出目录或任何TVFS完全限定的路径名。 如果是 给出目录名,然后MLSD必须返回一个列表 命名目录的内容,否则发出501回复,和 不会打开数据连接。 ...
如果没有给出参数,那么MLSD必须返回一个列表 当前工作目录的内容,而MLST必须返回一个 列出提供有关当前工作目录的信息 本身。 ...
...
如果Client-FTP发送了无效参数,则服务器-UT必须 回复,错误代码为501。
MLSD
和*.*
不是目录名,因此如果*.zip
发送TIdFTP.List()
或MLSD *.*
命令,服务器将失败。因此,MLSD *.zip
和TIdFTP.UseMLIS
在您的情况下可能都是True(TIdFTP.CanUseMLS
默认为True,而UseMLIS
在现代FTP服务器上通常为True)。
CanUseMLS
命令不支持像MLSD
/ LIST
命令那样的服务器端过滤。因此,您不能将NLST
和*.*
与*.zip
一起使用。您必须检索完整的目录列表,然后忽略您不感兴趣的任何条目。否则,在调用MLSD
之前将TIdFTP.UseMLIS
设置为False,但是您冒着{{1}的风险错误地解析某些服务器的目录列表,因为TIdFTP.List()
命令使用的格式从未标准化,并且在整个Internet上使用了数百种自定义格式(以及Indy 10中为什么TIdFTP.DirectoryListing
包括使用LIST
时的数十个列表解析器。与TIdFTP
不同,LIST
具有标准化格式(这就是为什么它首先被引入,以替换MLSx
的缺点)。
因此,这一切归结为 - 当LIST
和TIdFTP.UseMLIS
都为True时,TIdFTP.CanUseMLS
必须必须为空白或目录,不文件掩码。
TIdFTP.List()
documentation 表示ASpecifier
可以在内部调用TIdFTP.ExtListDir()
发送List()
命令,但没有具体提及此特定内容在这种情况下对MLSD
参数的限制:
如果CanUseMLS包含True,则调用ExtListDir以在ADest参数变量中捕获并存储FTP MLSD命令的结果,而不是LIST或NLST命令。在这种情况下,List方法中不执行其他处理,并退出该方法。
当ADetails为False时,只使用FTP NLST命令在ADest字符串列表中返回文件或目录名称。当ADetails为True时,List可以使用FTP LIST命令返回FTP服务器相关的详细信息,包括文件大小,修改日期以及所有者,组和用户的文件权限。
TIdFTP.ExtListDir()
documentation 表明其输入参数必须是目录名,但是:
ExtListDir支持的MLSD命令接受目录列表中的可选目录名称或Adirectory中的相对路径。如果在ADirectory中传递了空字符串,则当前目录用于目录列表操作。
旁注:ASpecifier
属性会告诉您TIdFTP.DirFormat
解析结果后检测到的列表格式。或者,您可以查看TIdFTP.DirectoryListing
的{{1}}和Details
属性(将其类型转换为UsedMLS
以访问属性)以推断{{1}发送的命令(如果成功的话)。
答案 1 :(得分:0)
另一种解决方案是包括
IdAllFTPListParsers
在您的uses
子句中并禁用UseMLIS
。
像这样:
uses
....
IdAllFTPListParsers;
.....
procedure TForm1.DoThis;
var
i: integer;
begin
if not IDFTP1.Connected then IDFTP1.Connect;
IDFTP1.UseMLIS:= false;
IDFTP1.List;
for i:= 0 to IDFTP1.DirectoryListing.Count -1 do begin
.. process directory items.
IdFTP1.TransferType:= ftBinary;
..Get your files