【问题标题】:How to download a file with progress with IdHTTP via https如何通过 https 使用 IdHTTP 下载有进度的文件
【发布时间】:2015-02-11 15:20:16
【问题描述】:

我正在尝试使用 indy10 http 组件 TIdHttp 下载文件,同时获得进度,我刚刚在应用程序文件夹中设置了库,同时使用 http URL 的代码它可以工作并取得进展,但是使用 https 它什么也不做它不会引发任何异常:/

 with TIdHTTP.Create(nil) do
   begin
    IOHndl:=TIdSSLIOHandlerSocketOpenSSL.Create(nil);
    Request.BasicAuthentication:=True;
    HandleRedirects:=True;
    IOHandler:=IOHndl;
    OnWork:=FOnWork;
    OnWorkBegin:=FOnWorkBegin;
    OnWorkEnd:=FOnWorkEnd;
    Get(FUrl,FStream);
end;

最好的问候

【问题讨论】:

  • 程序真正“什么都不做”的唯一时间是它被终止的时候。使用调试器暂停您的程序并查看调用堆栈。这将向您展示该程序的真正作用。
  • @RobKennedy 大多数人都知道他的意思。并且不必回答问题
  • 也许“大多数人”都知道,但我不知道,@Jens。我们在这里不需要更多不精确的问题。我指出了它的不精确性,并就如何修复它提供了建议。如果知道,那么也许你可以为我解释一下:程序实际上在做什么?
  • 如果你能给我一个通过 SSL 下载的文件,那么我可以。
  • @Jens,您声称大多数人都知道该用户在说该程序“什么都不做”时的意思,我假设您将自己包括在该组中。如果您知道它的含义,为什么需要更多信息来告诉它的含义? (如果你真的需要一个任意的 HTTPS 地址,这个页面的地址就可以了。)

标签: delphi ssl https indy


【解决方案1】:

首先你必须创建一个小类来包装 HTTP 组件:

unit IdHTTPProgressU;

interface

uses
  Classes, IdBaseComponent, IdComponent, IdTCPConnection, IdTCPClient, IdHTTP, IdSSLOpenSSL;

{$M+}

type
  TIdHTTPProgress = class(TIdHTTP)
  private
    FProgress: Integer;
    FBytesToTransfer: Int64;
    FOnChange: TNotifyEvent;
    IOHndl: TIdSSLIOHandlerSocketOpenSSL;
    procedure HTTPWorkBegin(ASender: TObject; AWorkMode: TWorkMode; AWorkCountMax: Int64);
    procedure HTTPWork(ASender: TObject; AWorkMode: TWorkMode; AWorkCount: Int64);
    procedure HTTPWorkEnd(Sender: TObject; AWorkMode: TWorkMode);
    procedure SetProgress(const Value: Integer);
    procedure SetOnChange(const Value: TNotifyEvent);
  public
    Constructor Create(AOwner: TComponent);
    procedure DownloadFile(const aFileUrl: string; const aDestinationFile: String);
  published
    property Progress: Integer read FProgress write SetProgress;
    property BytesToTransfer: Int64 read FBytesToTransfer;
    property OnChange: TNotifyEvent read FOnChange write SetOnChange;
  end;

implementation

uses
  Sysutils;
{ TIdHTTPProgress }

constructor TIdHTTPProgress.Create(AOwner: TComponent);
begin
  inherited;
  IOHndl := TIdSSLIOHandlerSocketOpenSSL.Create(nil);
  Request.BasicAuthentication := True;
  HandleRedirects := True;
  IOHandler := IOHndl;
  ReadTimeout := 30000;
  OnWork := HTTPWork;
  OnWorkBegin := HTTPWorkBegin;
  OnWorkEnd := HTTPWorkEnd;
end;

procedure TIdHTTPProgress.DownloadFile(const aFileUrl: string; const aDestinationFile: String);
var
  LDestStream: TFileStream;
  aPath: String;
begin
  Progress := 0;
  FBytesToTransfer := 0;
  aPath := ExtractFilePath(aDestinationFile);
  if aPath <> '' then
    ForceDirectories(aPath);

  LDestStream := TFileStream.Create(aDestinationFile, fmCreate);
  try
    Get(aFileUrl, LDestStream);
  finally
    FreeAndNil(LDestStream);
  end;
end;

procedure TIdHTTPProgress.HTTPWork(ASender: TObject; AWorkMode: TWorkMode; AWorkCount: Int64);
begin
  if BytesToTransfer = 0 then // No Update File
    Exit;

  Progress := Round((AWorkCount / BytesToTransfer) * 100);
end;

procedure TIdHTTPProgress.HTTPWorkBegin(ASender: TObject; AWorkMode: TWorkMode; AWorkCountMax: Int64);
begin
  FBytesToTransfer := AWorkCountMax;
end;

procedure TIdHTTPProgress.HTTPWorkEnd(Sender: TObject; AWorkMode: TWorkMode);
begin
  FBytesToTransfer := 0;
  Progress := 100;
end;

procedure TIdHTTPProgress.SetOnChance(const Value: TNotifyEvent);
begin
  FOnChance := Value;
end;

procedure TIdHTTPProgress.SetProgress(const Value: Integer);
begin
  FProgress := Value;
  if Assigned(FOnChance) then
    FOnChance(Self);
end;

end.

我不会详细介绍 calss:只是说它实际上包装了一个 TIdhttp 组件并分配 3 个事件:OnBeginonWorkOnEnd

方法DownloadFile 进行实际下载,

然后当你必须使用它时,你可以这样做:
在空窗体上放置一个 Button 和一个 PrograssBar。将IdHTTPProgressU 添加到使用列表中。

声明一个TIdHTTPProgress 和一个本地onChangeEvent 的变量

你的表单定义应该是这样的:

type
  TForm1 = class(TForm)
    Button1: TButton;
    ProgressBar1: TProgressBar;
    procedure FormCreate(Sender: TObject);
    procedure Button1Click(Sender: TObject);
  private
    procedure IdHTTPProgressOnChange(Sender : TObject);
  public
    IdHTTPProgress: TIdHTTPProgress;
  end;

然后你只需要实现方法:

    { TForm1 }

    procedure TForm1.Button1Click(Sender: TObject);
    begin
       IdHTTPProgress.OnChange := IdHTTPProgressOnChance;
          IdHTTPProgress.OnChance := IdHTTPProgressOnChance;
   IdHTTPProgress.DownloadFile('https://wordpress.org/latest.zip', 'latest.zip');
    end;

    procedure TForm1.FormCreate(Sender: TObject);
    begin
      IdHTTPProgress := TIdHTTPProgress.Create(Self);
    end;

    procedure TForm1.IdHTTPProgressOnChance(Sender: TObject);
    begin
      ProgressBar1.Position := TIdHTTPProgress(Sender).Progress;
      Application.ProcessMessages;
    end;

就是这样。试试看。

【讨论】:

  • 问题中的代码有什么问题?您的代码没有演示 HTTPS;问题是纯 HTTP 已经可以正常工作,那么您的代码实际解决了什么问题? (另外,你想要的词是change,而不是chance。详情请查字典。)
  • @RobKennedy 我错过了 HTTPS 部分,但没有区别。现在我添加了 https 并且我的示例仍然有效。
  • TIdSSLIOHandlerSocketOpenSSL 在哪里被销毁?好像没有。它看起来像它泄漏内存。否则我可能会 +1。此外,您应该考虑解决这些语法问题。
猜你喜欢
  • 2012-07-16
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-02-02
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多