4

Indy コンポーネントを使用してインターネットからファイルをダウンロードする次のコードを検討してください。

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。そのため、ファイルに解凍する前に、圧縮データ全体をメモリにキャッシュします。

<meta>HTML が HTMLタグ (最も重要なのはデータの Charset 値)を介して新しい値で HTTP ヘッダー値をオーバーライドする場合、HTML の解析が必要になることがあります。これTIdHTTPにより、データがString. フラグを有効にhoNoParseMetaHTTPEquivすると、その解析が無効になり、HTML データのキャッシュが無効になります (圧縮も使用されていない場合)。

于 2012-05-15T20:08:51.833 に答える
3

私は問題を見つけました。サーバー側で IndysServeFile関数を使用していました。

この関数は、 が指定されているかどうかをチェックし、Content-Type指定されていない場合は を自動的に検出しますContent-Type。問題は、私が変更しなかったことContent-Typeであり、デフォルトでは text/html でした。content-type を変更すると、クライアントはストリームに直接書き込みます。

この種の問題を回避するために、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 に答える