【问题标题】:How do I send a TMemoryStream using Indy's IdTrivialFTP?如何使用 Indy 的 IdTrivialFTP 发送 TMemoryStream?
【发布时间】:2009-12-29 21:38:59
【问题描述】:

我使用的是 Delphi 2010 和随附的 Indy 10。 MemStream 是一个 TMemoryStream,它包含从网站下载的文件。

IdTrivialFTP1 := TIdTrivialFTP.Create(nil);
try
  IdTrivialFtp1.Name := 'IdTrivialFTP1';
  IdTrivialFTP1.Host := 'my-tftp-server-name.contoso.com';
  IdTrivialFTP1.Port := 69;
  IdTrivialFTP1.ReceiveTimeout := 4000;

  MemStream.Position := 0;
  IdTrivialFTP1.Put(MemStream, sFileName);
finally
  FreeAndNil(IdTrivialFTP1);
end;

每当我运行此代码时,我都会收到错误消息:

Project TestProject.exe 引发异常类 ERangeError,并带有消息“范围检查错误”。

我一直在用谷歌搜索来理解这个错误,但我目前不知所措。我还看到只有 1 个example of how to perform a TFTP PUT 使用 Indy 组件。

有什么想法吗?

更新: 如果我稍微追踪一下错误,我发现错误是从第 272 行的“IdTrivialFTP.pas”中抛出的:

    CurrentDataBlk := WordToStr(GStack.HostToNetwork(Word(TFTP_DATA)))
+ WordToStr(GStack.HostToNetwork(BlockCtr));

为清楚起见,以下是该代码的上下文:

if BlockCtr > PrevBlockCtr then
  begin
    DataLen := IndyMin(BufferSize - hdrsize, SourceStream.Size - SourceStream.Position);
    SetLength(CurrentDataBlk, DataLen + hdrsize);
    CurrentDataBlk := WordToStr(GStack.HostToNetwork(Word(TFTP_DATA))) + WordToStr(GStack.HostToNetwork(BlockCtr));
    SetLength(CurrentDataBlk, DataLen + hdrsize);
    //SourceStream.ReadBuffer(CurrentDataBlk[hdrsize+1], DataLen);
    DoWork(wmWrite, DataLen);
    TerminateTransfer := DataLen < BufferSize - hdrsize;
    PrevBlockCtr := BlockCtr;
  end;
  Send(FPeerIP, FPeerPort, CurrentDataBlk);
until False;  { repeat }

【问题讨论】:

    标签: delphi ftp indy


    【解决方案1】:

    很好地确定了异常的来源。当您遇到异常时,这应该始终是您做的第一件事。

    您使用的 Indy 代码已损坏。即使没有范围检查错误,它仍然不会从源流中发送任何数据。您可以自己看到读取流内容的行已被注释掉。它仍然在今天的开发快照中被注释掉,看起来已经有两年多没有人处理这个文件了。事实上,自从文件在修订版 7 中添加到 Subversion 存储库后,该行就被注释掉了。

    放弃TIdTrivialFTP,改用成熟的FTP客户端TIdFTP试试运气。

    【讨论】:

    • 某些系统,例如 VOIP 电话,使用 TFTP 而不是 FTP。
    【解决方案2】:

    D2010 随附的 Indy 10 版本不是可用的最新 Indy 10 修订版。您引用的被破坏的 Indy 代码在当前版本中不再存在。 TIdTrivialFTP 不久前被重写以解决很多问题(不过,我当时忘记检查它。我现在已经这样做了)。请从 Indy 的 SVN 服务器或 Fulgan 镜像下载最新的 Indy 10 快照(您必须等待一天才能赶上)。下载链接可在 Indy 的网站上找到。

    【讨论】:

    • 我有来自 svn.atozed.com 的第 3979 版的 IdTrivialFTP.pas,SourceStream.ReadBuffer 行仍然被注释掉。
    • 检查位于 \Indy10\branches\Tiburon\Lib\Protocols 的 IdTrivialFTP.pas。
    • 另外,我刚刚意识到我检查了修订版 3980,所以这可能是您没有看到它的原因。
    • 啊,是的。我现在看到开发是在 Tiburon 分支 上进行的,而不是在主干上。还要多久才能修好,雷米? Tiburon 是 Delphi 2009 的代号,不是吗?我从没想过要从一个以过时代号命名的分支中获取最新版本。
    • 是的,Tiburon 是 Delphi 2009 的代号。那是我们开始 Indy 的 Unicode 集成的时候。它还没有完成。 Tiburon 分支何时合并到主干中没有 ETA。 Indy 网站上的下载说明中说明了使用 Branch 而不是 Trunk 获取最新代码。
    【解决方案3】:

    您可以自己轻松解决这个问题:

    • 在 IdTrivialFTP1.Name 行设置断点。
    • 按 F9 运行您的应用程序。执行任何触发代码以对文件进行 FTP 传输的操作。
    • 当 IDE 在断点处停止时,按 F8 以逐行执行代码。
    • 注意您按 F8 并触发异常的行。这就是问题所在。

    由于您只有两行应该触发范围检查错误(分配 Port 和 ReceiveTimeout 的行),因此找出罪魁祸首应该是 +trivial+(双关语)。我怀疑是端口设置。

    另外,不要忘记 Indy 附带完整的源代码。如果您将项目的编译器选项设置为使用调试 DCU,您也可以对此进行跟踪。 (项目|选项|编译器)

    【讨论】:

    • 问题出在 Indy 源代码中,但老实说,我不知道如何解决。我会用详细信息更新我的评论。
    【解决方案4】:

    我的回答是; Indy 很烂,放弃它并使用 Francois Piette 的 ICS 组件。

    W

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2014-12-31
      • 1970-01-01
      • 1970-01-01
      • 2021-05-12
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多