使用 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;