如何使用 Indy 的 IdTrivialFTP 发送 TMemoryStream?

发布于 2024-08-16 20:47:42 字数 1624 浏览 6 评论 0原文

我正在使用 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 个如何使用 Indy 组件执行 TFTP PUT 的示例

有什么想法吗?

更新: 如果我稍微追踪一下错误,我发现错误是从第 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 }

I am using Delphi 2010 and Indy 10 that ships with it. The MemStream is a TMemoryStream and it contains a file downloaded from a website.

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;

Whenever I run this code, I get the error:

Project TestProject.exe raised exception class ERangeError with message 'Range check error'.

I've been doing quite a bit of google-ing to understand this error, but I'm currently at a loss. I've also seen only 1 example of how to perform a TFTP PUT using Indy components.

Any ideas?

UPDATE:
If I trace into the error a bit, I find that the error is being thrown from within "IdTrivialFTP.pas" on line 272:

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

For clarity, here is the context of that code:

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 }

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

尽揽少女心 2024-08-23 20:47:42

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

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

放弃 TIdTrivialFTP 并使用成熟的 FTP 客户端试试运气,TIdFTP< /代码>。

Good job determining the source of the exception. That should always be the first thing you do when you encounter an exception.

The Indy code you're using is broken. Even if there weren't a range-check error, it still wouldn't send any data from the source stream. You can see for yourself that the line that reads the contents of the stream has been commented out. It's still commented out in today's development snapshot, and it looks like it's been over two years since anyone has worked on that file. In fact, that line has been commented out ever since the file was added to the Subversion repository in revision 7.

Ditch TIdTrivialFTP and try your luck with the full-fledged FTP client instead, TIdFTP.

倾`听者〃 2024-08-23 20:47:42

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

The version of Indy 10 that shipped with D2010 is NOT the latest Indy 10 revision that is available. The Indy code you have quoted as being broken does not exist in the current version anymore. TIdTrivialFTP was re-written awhile back ago to fix a lot of issues (I forgot to check it in at the time, though. I have done so now). Please download the latest Indy 10 snapshot from Indy's SVN server or Fulgan mirror (you will have to wait a day for it to catch up). Download links are available on Indy's website.

岁吢 2024-08-23 20:47:42

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

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

由于只有两行应该触发范围检查错误(分配端口和 ReceiveTimeout 的行),因此找出哪一行是罪魁祸首应该是微不足道的(双关语)。我怀疑是端口设置的问题。

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

You can resolve this pretty easily yourself:

  • Set a breakpoint on the line with IdTrivialFTP1.Name.
  • Hit F9 to run your app. Do whatever triggers the code to FTP the file.
  • When the IDE stops on the breakpoint, hit F8 to step line by line through the code.
  • Note the line where you hit F8 and an exception is triggered. That's the problem line.

Since you only have two lines that should trigger a range check error (the ones assigning Port and ReceiveTimeout), finding out which one is the culprit should be +trivial+ (pun intended). I'd suspect it's the port setting.

Also, don't forget that Indy comes with full source code. You can also trace into that as well, if you set your project's compiler options to use debug DCUs. (Project|Options|Compiler)

享受孤独 2024-08-23 20:47:42

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

My answer would have been; Indy sucks, ditch it and use Francois Piette's ICS components.

W

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文