【问题标题】:Indy TIdFTP "Out of Memory" error when downloading a large file下载大文件时出现 Indy TIdFTP“内存不足”错误
【发布时间】:2021-04-08 19:17:42
【问题描述】:

我正在使用TIdFTP (Indy 10.6) 上传超过 1GB 的大文件。

当我想下载该文件时,我收到一条错误消息“内存不足”。

这是我的代码:

var
  FTPfile: TMemoryStream;
begin
  ...
  FTPFile := TMemoryStream.Create;
  ...
  TRY
    IdFTP1.Get ('Myfile.pdf', FTPfile, false);
    FTPfile.Position := 0;
  EXCEPT
    On E: Exception do
      ShowMessage (E.Message);
  END;

我使用的是 32 位版本的 Windows。

有解决这个问题的方法吗?

【问题讨论】:

  • 您正在将文件加载到内存中(您发现这是有限的),您可以通过使用 TFilestream 将文件加载到磁盘来轻松解决此问题。
  • 感谢您的帮助。
  • 另外,你应该去掉try..except。即使没有此块,您也会收到一个带有异常的消息框。而这个块是有害的:它会让例程在异常之后继续,这可能会导致更多的问题。相反,使用try..finally 来保护流对象。

标签: delphi indy10


【解决方案1】:

您正在尝试将 1GB 文件下载到 TMemoryStream。除了通常是一个坏主意之外,这样做的主要问题是 FTP 协议不报告正在传输的文件的大小,因此TIdFTP.Get() 无法预先分配TMemoryStream前面的内部缓冲区。因此,随着文件的下载,TMemoryStream.Capacity 将不得不增长很多倍,并且每次它都会分配一个全新的缓冲区,将现有数据复制到其中,并释放旧缓冲区。这意味着在增长操作期间,内存中存在 2 个缓冲区的时间窗口很小。因此,您实际上使用的内存比您想象的要多得多。而在内存中存储一​​个 1GB 的文件确实是在推动 32 位进程甚至可以分配多少内存的极限。

最终,TMemoryStream 将变得如此之大,以至于系统无法再分配第二个缓冲区,从而失败并出现“内存不足”错误。

您可以尝试使用TIdFTP.Size() 或TIdFTP.List() 提前确定远程文件的大小,相应地设置TMemoryStream.Capacity,然后调用TIdFTP.Get()。这样,只执行了 1 次内存分配。

另外,当你用完它时,确保你Free()TMemoryStream,否则你会泄漏它能够分配的任何内存。

但实际上,您应该将文件下载到磁盘。您可以为此使用TFileStream,但TIdFTP.Get() 有一个重载,它将本地文件路径作为目标而不是TStream。

如果您需要访问内存中的文件数据,您可以在下载完成后根据需要对其进行读取/内存映射。

【讨论】:

  • 感谢您的帮助。那么 Remy,你是在建议我使用 TFileStream 吗?
  • @Amélie 是的。 TIdFTP.Get() 的另一个重载已经为您处理了。
  • @Remy:我在管理文件的打开时遇到了困难。该文件已下载到磁盘,但我收到一条错误消息,告诉我无法创建或打开该文件,因为它正在被另一个进程使用。我的代码中有一些不好的处理。你用什么代码用“TFileStream”做这个?
  • @Amélie 听起来你在使用完FreeTFileStream。就像您的TMemoryStream 一样。正如我之前所说,您应该使用TIdFTP.Get() 的第二个重载,它采用目标文件路径而不是TStream,让它在内部处理自己的流。
  • 请问是这样吗? FichierFTP := TFileStream.Create(PChar(ExtractFilePath(Application.ExeName)+'\Temps\' + 'MyFile.pdf') , fmCreate ); TRY Form1.IdFTP1.Get(DBEditNomFichierHDD.Text ,PChar(ExtractFilePath(Application.ExeName)+'\Temps\' + DBEditNomFichierHDD.Text) , true ); FichierFTP.Position:= 0 ; except On E:Exception do // ShowMessage(E.Message); ShowMessage('Ce fichier est introuvable sur le serveur'); END; FichierFTP.Free;
猜你喜欢
  • 1970-01-01
  • 2021-04-23
  • 1970-01-01
  • 1970-01-01
  • 2015-05-02
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多