我正在尝试生成与某个文件掩码匹配的文件列表,而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中的一个错误?
我需要"细节",所以我也可以比较时间戳和大小.
Rem*_*eau 11
这不是一个错误TIdFTP
.这在Indy文档中更是一个遗漏.
EIdReplyRFCError
表示FTP服务器本身正在报告错误以响应TIdFTP.List()
正在发送的命令.根据ADetails
参数和TIdFTP
's UseMLIS
+ CanUseMLS
属性的值,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]
Run Code Online (Sandbox Code Playgroud)
从而:
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 *.*'
Run Code Online (Sandbox Code Playgroud)
请注意,所有"失败"的命令都有一些共同点 - 它们可能正在发送MLSD ASpecifier
命令.
根据RFC 959,它定义LIST
和NLST
命令:
列表(列表)
此命令使列表从服务器发送到被动DTP. 如果路径名指定目录或其他文件组,则服务器应传输指定目录中的文件列表.如果路径名指定文件,则服务器应发送有关该文件的当前信息.null参数表示用户当前的工作或默认目录. ...
姓名单(NLST)
此命令导致目录列表从服务器发送到用户站点. pathname应指定目录或其他特定于系统的文件组描述符; null参数表示当前目录....
根据RFC 3659,定义MLSD
命令:
MLST和MLSD命令每个都允许一个可选参数. 此参数可以是目录名称,也可以是MLST文件名. 出于这些目的,"文件名"是服务器NVFS中不是目录的任何实体的名称.在支持TVFS的情况下,可以给出在当前工作目录中有效的任何TVFS相对路径名,或任何TVFS完全限定路径名. 如果给出了目录名,则MLSD必须返回指定目录内容的列表,否则它将发出501回复,并且不会打开数据连接. ...
如果没有给出参数,那么MLSD必须返回当前工作目录内容的列表,并且MLST必须返回一个列表,该列表提供有关当前工作目录本身的信息....
...
如果Client-FTP发送无效参数,则服务器FTP必须回复,错误代码为501.
*.*
并且*.zip
不是目录名,因此如果TIdFTP.List()
发送MLSD *.*
或MLSD *.zip
命令,服务器将失败.所以,按理说,TIdFTP.UseMLIS
并TIdFTP.CanUseMLS
在你的情况可能都为真(UseMLIS
默认为true,并且CanUseMLS
通常是真正的现代FTP服务器).
该MLSD
命令不支持LIST
/ NLST
commands这样的服务器端过滤.所以你不能用的东西喜欢*.*
和*.zip
有MLSD
.您必须检索完整的目录列表,然后忽略您不感兴趣的任何条目.否则,TIdFTP.UseMLIS
在调用之前设置为False TIdFTP.List()
,但是您可能会TIdFTP.DirectoryListing
错误地解析某些服务器的目录列表,因为该LIST
命令从未标准化,并且在整个互联网上使用了数百种自定义格式(为什么TIdFTP
在Indy 10 LIST
中使用时会包含数十种列表解析器).不同的是MLSx
,它具有标准化的格式(这就是为什么它首先被引入,以替换它的缺点LIST
).
因此,这一切都归结为 - 当TIdFTP.UseMLIS
和TIdFTP.CanUseMLS
都是真的时,ASpecifier
必须是空白或目录,而不是文件掩码.
该TIdFTP.List()
文件 确实是状态List()
可能内部调用TIdFTP.ExtListDir()
发送MLSD
命令,但它并没有特别提到在这个特别的限制,ASpecifier
在这种情况下参数:
如果CanUseMLS包含True,则调用ExtListDir以在ADest参数变量中捕获并存储FTP MLSD命令的结果,而不是LIST或NLST命令.在这种情况下,List方法中不执行其他处理,并退出该方法.
当ADetails为False时,使用FTP NLST命令仅在ADest字符串列表中返回文件或目录名称.当ADetails为True时,List可以使用FTP LIST命令返回FTP服务器相关的详细信息,包括文件大小,修改日期以及所有者,组和用户的文件权限.
该TIdFTP.ExtListDir()
文档 确实声明其输入参数必须是目录名,但是:
ExtListDir支持的MLSD命令接受目录列表的Adirectory中的可选目录名或相对路径.如果在ADirectory中传递空字符串,则当前目录用于目录列表操作.
在旁注:该TIdFTP.DirFormat
属性将告诉您在TIdFTP.DirectoryListing
解析结果后检测到哪种列表格式.或者你可以看看Details
和UsedMLS
属性TListFTP.ListResult
(类型投它TIdFTPListResult
来访问属性)来推断该命令由发送TIdFTP.List()
(如果成功的话).