使用 Indy 处理 BabyFTP MKD 250 响应
Handling BabyFTP MKD 250 response with Indy
我正在使用 BabyFTP 作为 Delphi 10.1 Berlin 应用程序的嵌入式 FTP 服务器。尽管我仍然不确定它是否是我可以使用的最好的轻量级 FTP 服务器,但它似乎运行良好......除了一个细节:
在成功的 MKD 命令中,BabyFTP 响应 250,而不是预期的(RFC 和 Indy)257。因此 TIdFTP 引发了一个 EIdReplyRFCError 异常,它中断了我正在尝试做的事情的流程(将 blob 字段保存到文件):
s := TBytesStream.Create;
Try
Field.SaveToStream(s);
MakeDir(TPath.GetDirectoryName(url));
Put(s, url);
Finally
s.Free;
End;
当然,我知道我可以将 MakeDir 行包装在 Try Except 块中并忽略特定的异常类型。但这似乎有点冒险,因为从引发的异常来看,我无法确定我得到了 250 或其他一些真正的错误。
我试过查看 Indy 的响应代码是否可以某种方式配置,但它们似乎是硬编码在特定方法中的。子类化 TIdFTP 是不可行的,因为这些方法不是虚拟的。我可以自定义 IdFTP.pas 单元,但我不想这样做,因为我在团队中工作,我更喜欢不必将补丁分发到标准 Delphi 单元。
我可以使用另一台 FTP 服务器...但我想它们中的大多数都有一些不完全标准的功能,例如这个。
有人知道其他解决方法吗?雷米?
当 ErrorCode
属性 等于 250 时,您可以只处理 EIdReplyRFCError
的特定情况,在任何其他情况下重新加注。
s := TBytesStream.Create;
Try
Field.SaveToStream(s);
Try
MakeDir(TPath.GetDirectoryName(url));
Except
on E: EIdReplyRFCError do
if E.ErrorCode <> 250 then raise;
end
Put(s, url);
Finally
s.Free;
End;
Ondrej 的回答解释了如何解决 TIdFTP.MakeDir()
中处理 250 回复的问题。
请注意 TIdFTP.MakeDir()
只是 TIdTCPConnection.SendCmd()
的包装:
procedure TIdFTP.MakeDir(const ADirName: string);
begin
SendCmd('MKD ' + ADirName, 257); {do not localize}
end;
SendCmd()
是 public
,因此另一种解决方案是直接调用 SendCmd()
并告诉它 250
是可接受的回复代码:
s := TBytesStream.Create;
Try
Field.SaveToStream(s);
//MakeDir(TPath.GetDirectoryName(url));
SendCmd('MKD ' + TPath.GetDirectoryName(url), [250, 257]);
Put(s, url);
Finally
s.Free;
End;
或者,要接受任何 2xx
回复码,您可以这样做:
s := TBytesStream.Create;
Try
Field.SaveToStream(s);
//MakeDir(TPath.GetDirectoryName(url));
if (SendCmd('MKD ' + TPath.GetDirectoryName(url)) div 100) <> 2 then
RaiseExceptionForLastCmdResult;
Put(s, url);
Finally
s.Free;
End;
我正在使用 BabyFTP 作为 Delphi 10.1 Berlin 应用程序的嵌入式 FTP 服务器。尽管我仍然不确定它是否是我可以使用的最好的轻量级 FTP 服务器,但它似乎运行良好......除了一个细节:
在成功的 MKD 命令中,BabyFTP 响应 250,而不是预期的(RFC 和 Indy)257。因此 TIdFTP 引发了一个 EIdReplyRFCError 异常,它中断了我正在尝试做的事情的流程(将 blob 字段保存到文件):
s := TBytesStream.Create;
Try
Field.SaveToStream(s);
MakeDir(TPath.GetDirectoryName(url));
Put(s, url);
Finally
s.Free;
End;
当然,我知道我可以将 MakeDir 行包装在 Try Except 块中并忽略特定的异常类型。但这似乎有点冒险,因为从引发的异常来看,我无法确定我得到了 250 或其他一些真正的错误。
我试过查看 Indy 的响应代码是否可以某种方式配置,但它们似乎是硬编码在特定方法中的。子类化 TIdFTP 是不可行的,因为这些方法不是虚拟的。我可以自定义 IdFTP.pas 单元,但我不想这样做,因为我在团队中工作,我更喜欢不必将补丁分发到标准 Delphi 单元。
我可以使用另一台 FTP 服务器...但我想它们中的大多数都有一些不完全标准的功能,例如这个。
有人知道其他解决方法吗?雷米?
当 ErrorCode
属性 等于 250 时,您可以只处理 EIdReplyRFCError
的特定情况,在任何其他情况下重新加注。
s := TBytesStream.Create;
Try
Field.SaveToStream(s);
Try
MakeDir(TPath.GetDirectoryName(url));
Except
on E: EIdReplyRFCError do
if E.ErrorCode <> 250 then raise;
end
Put(s, url);
Finally
s.Free;
End;
Ondrej 的回答解释了如何解决 TIdFTP.MakeDir()
中处理 250 回复的问题。
请注意 TIdFTP.MakeDir()
只是 TIdTCPConnection.SendCmd()
的包装:
procedure TIdFTP.MakeDir(const ADirName: string);
begin
SendCmd('MKD ' + ADirName, 257); {do not localize}
end;
SendCmd()
是 public
,因此另一种解决方案是直接调用 SendCmd()
并告诉它 250
是可接受的回复代码:
s := TBytesStream.Create;
Try
Field.SaveToStream(s);
//MakeDir(TPath.GetDirectoryName(url));
SendCmd('MKD ' + TPath.GetDirectoryName(url), [250, 257]);
Put(s, url);
Finally
s.Free;
End;
或者,要接受任何 2xx
回复码,您可以这样做:
s := TBytesStream.Create;
Try
Field.SaveToStream(s);
//MakeDir(TPath.GetDirectoryName(url));
if (SendCmd('MKD ' + TPath.GetDirectoryName(url)) div 100) <> 2 then
RaiseExceptionForLastCmdResult;
Put(s, url);
Finally
s.Free;
End;