Delphi 如何通过https通过IdHTTP下载具有进度的文件

Delphi 如何通过https通过IdHTTP下载具有进度的文件,delphi,ssl,https,indy,Delphi,Ssl,Https,Indy,我正在尝试使用indy10 http组件TIdHttp下载一个文件,在获得进度的同时,我刚刚在应用程序文件夹中设置了库,同时使用http URL代码,它可以正常工作并进行进度,但使用https,它什么也不做,也不会引发任何异常:/ with TIdHTTP.Create(nil) do begin IOHndl:=TIdSSLIOHandlerSocketOpenSSL.Create(nil); Request.BasicAuthentication:=True;

我正在尝试使用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;

致以最诚挚的问候

首先,您必须创建一个小型类来包装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.
然后,您只需实现以下方法:

    { 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;

就这样。试试看

程序真正“什么都不做”的唯一时间是终止时。使用调试器暂停程序并查看调用堆栈。“这将向你展示这个项目真正在做什么。”罗伯肯尼迪说,“大多数人都知道他的意思。“你也不必问这个问题,也许“大多数人”都知道,但我不知道,”詹斯说。我们不需要更多不精确的问题。我指出了它的不精确性,并给出了如何修复它的建议。如果你知道,那么也许你可以为我解释一下:这个程序实际上在做什么?如果你能给我一个通过SSL下载的文件,那么我就可以。@Jens,你声称大多数人都知道这个用户说这个程序“什么都不做”的意思,我想你也包括在这个群体中。如果你知道这意味着什么,为什么你需要更多的信息来告诉我这意味着什么?(如果你真的需要一个任意的HTTPS地址,这个页面的地址就可以了。)问题中的代码怎么了?您的代码没有演示HTTPS;问题是普通HTTP已经可以正常工作了,那么您的代码实际解决了什么问题呢?(还有,你想要的是变化,而不是偶然。查字典了解详情。)@RobKennedy我错过了HTTPS部分,但没有区别。现在我已经添加了https,我的示例仍在运行。
TIdSSLIOHandlerSocketOpenSSL
在哪里被销毁?看起来没有。看起来好像是内存泄漏。否则我可能会+1。此外,你应该考虑在你的语法问题。
    { 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;