4

考虑以下使用 Indy 组件从 Internet 下载文件的代码:

procedure TForm26.Button1Click(Sender: TObject);
var
  vFileStream : TStream;
begin
  DeleteFile('C:\test.exe');
  vFileStream := TFileStream.Create('C:\test.exe', fmCreate);
  IdHTTP1.Get('SomeUrl', vFileStream);
  vFileStream.Free;
end;

我收到内存不足异常。正在发生的事情是,除了我正在使用的事实之外,TFileStream正在写入它的字节不会直接进入磁盘,而是会保留在内存中直到get终止。

我要下载的文件非常非常大。

有谁知道如何在不出现内存不足异常的情况下下载大文件?

Delphi 2010 和来自 Indy 的 SVN 的最新 Indy 10。

编辑

那不是FileStream问题。这是一个Indy问题。Indy 以某种方式在将文件写入流之前将其缓存在内存中。

4

3 回答 3

5

TIdHTTP如果数据被压缩,或者数据是 HTML 并且TIdHTTP.HTTPOptions属性不包含hoNoParseMetaHTTPEquiv标志,则将整个文件下载到内存中。

Indy 还不支持 HTTP 的流式解压缩(不过它支持 FTP),因此TIdHTTP在将整个压缩数据缓存在内存中,然后再将其解压缩到文件中。

在 HTML 通过 HTML<meta>标记用新值覆盖 HTTP 标头值(最重要的是数据的 Charset 值)的情况下,有时需要解析 HTML,因此TIdHTTP当数据以String. 启用该hoNoParseMetaHTTPEquiv标志会禁用该解析,从而禁用 HTML 数据的任何缓存(除非也使用压缩)。

于 2012-05-15T20:08:51.833 回答
3

我发现了这个问题。我在服务器端使用了 IndysServeFile功能。

此函数检查是否Content-Type指定了 a,如果没有,它会自动检测Content-Type. 问题是我没有更改Content-Type它,默认情况下它是 text/html。更改内容类型使客户端直接写入流。

我认为该serveFile功能应始终设置正确Content-Type以避免此类问题。

在客户端,我发现这段代码对我有很大帮助:

  LParseHTML := IsContentTypeHtml(AResponse) and Assigned(AResponse.ContentStream) and not (hoNoParseMetaHTTPEquiv in FOptions);
  LCreateTmpContent := LParseHTML and not (AResponse.ContentStream is TCustomMemoryStream);
于 2012-05-15T20:37:43.693 回答
1

您是否尝试通过设置Request.ContentRangeStart和部分下载文件Request.ContentRangeEnd

于 2012-05-15T19:27:14.850 回答