How to download a file with progress with IdHTTP via https

青春壹個敷衍的年華 提交于 2019-12-09 06:54:53

问题


I'm trying to download a file using indy10 http components TIdHttp while getting the progress , I have just setted the libraries in the application folder while using the code for http URL it works and progress but with https it simply does nothing and it doesn't raises any exception :/

 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;

Best Regards


回答1:


First you have to create a small class to wrap the HTTP component:

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.

I wont go in to details with the calss: Just say that it bacally wraps a TIdhttp component in and assign the 3 events: OnBegin, onWork and OnEnd

The Method DownloadFile does the actually download,

Then when you have to use it you could do like this:
Place a Button and a PrograssBar on an empty form. Add IdHTTPProgressU to the uses list.

Declare a vaiable of TIdHTTPProgress and a local onChangeEvent

Your form definition should lokke like this:

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;

Then you just have to implement the methods:

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

Thats about it. Give it at try.



来源:https://stackoverflow.com/questions/28457925/how-to-download-a-file-with-progress-with-idhttp-via-https

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!