使用 Delphi 和 Indy 以编程方式通过 Progress 事件从 Internet 下载文件

Posted

技术标签:

【中文标题】使用 Delphi 和 Indy 以编程方式通过 Progress 事件从 Internet 下载文件【英文标题】:Download a File from internet programmatically with an Progress event using Delphi and Indy 【发布时间】:2011-01-12 04:07:00 【问题描述】:

我需要一种通过 HTTP 使用 Delphi 从 Internet 下载文件的方法, 其中包括一个 Progress 事件,我正在寻找一种使用 Indy 组件的方法。

我正在使用 Delphi 7。

【问题讨论】:

【参考方案1】:

我已经编写了这个示例,仅使用一个 HTTP GET,使用 Indy 10,希望它也适用于 Indy 9:

uses
  ... IdHTTP, IdComponent;

type
  TFormMain = class(TForm)
    ...
  private
    ...
    procedure HttpWork(ASender: TObject; AWorkMode: TWorkMode; AWorkCount: Int64);
  end;
...

procedure TFormMain.Button1Click(Sender: TObject);
var
  Http: TIdHTTP;
  MS: TMemoryStream;
begin
  Http := TIdHTTP.Create(nil);
  try
    MS := TMemoryStream.Create;
    try
      Http.OnWork:= HttpWork;

      Http.Get('http://live.sysinternals.com/ADExplorer.exe', MS);
      MS.SaveToFile('C:\ADExplorer.exe');

    finally
      MS.Free;
    end;
  finally
    Http.Free;
  end;
end;

procedure TFormMain.HttpWork(ASender: TObject; AWorkMode: TWorkMode; AWorkCount: Int64);
var
  Http: TIdHTTP;
  ContentLength: Int64;
  Percent: Integer;
begin
  Http := TIdHTTP(ASender);
  ContentLength := Http.Response.ContentLength;

  if (Pos('chunked', LowerCase(Http.Response.TransferEncoding)) = 0) and
     (ContentLength > 0) then
  begin
    Percent := 100*AWorkCount div ContentLength;

    MemoOutput.Lines.Add(IntToStr(Percent));
  end;
end;

【讨论】:

Response.ContentLength 值并不总是有效的。特别是,在使用“分块”传输编码的 HTTP 1.1 回复中,不允许使用“Content-Length”标头。在分块传输期间,数据的总大小无法提前知道,因为数据在多个块中传输,并且每个块在内部都有自己的大小。 更好?现在我在IdHTTP.pas 单元内使用与TIdCustomHTTP.ReadResult() 完全相同的条件 别忘了在 OnWork 活动中写上Application.ProcessMessages(); 不要使用Application.ProcessMessages()。这将为所有未决消息抽出消息队列,如果您不小心,可能会导致副作用和重入问题。最好使用TForm.Update() 方法来仅处理待处理的绘制消息而不处理其他消息。 与其避免Application.ProcessMessages(),不如设计您的应用程序,使其能够在文件下载期间处理接收消息。这可以通过将下载代码移动到一个线程中来完成(但您现在有两个 porbelms!),或者通过使用 Application.ProcessMessages() 并处理可能的情况(按钮单击、窗口关闭等)以防止重新进入问题 - - 通常最简单的方法是专门的下载对话框。如果您只使用TForm.Update(),您将导致您的应用程序无法响应用户交互。

以上是关于使用 Delphi 和 Indy 以编程方式通过 Progress 事件从 Internet 下载文件的主要内容,如果未能解决你的问题,请参考以下文章

delphi indy10 无法接收中文

delphi2007中间的indy控件里面base64编码器没有了DecodeToStream函数怎么办?

Delphi - Indy TIdHTTP方式创建程序外壳 - 实现可执行程序的自动升级

Delphi - Indy idMessage和idSMTP实现邮件的发送

Delphi、Indy TLS 1.2 和 TLS 1.3 开始状态码 403

使用 indy 10.5.8 在 Delphi 2010 中设置 KeepAlive 超时