Link to home
Start Free TrialLog in
Avatar of Adriaan Boshoff
Adriaan Boshoff

asked on

Downloading files using TIdHTTP INDY

I currently have a program that downloads a file from my VPS and extracts it. I want to make it download straight from the original website but it doesn't want to work. I want to make it download this link: https://bintray.com/oxidemod/builds/download_file?file_path=Oxide-Rust.zipĀ instead of this: http://41.185.91.51/RSM/Oxide-Rust.zip

I'm using Rad Studio 10.2

I did find this post but I'm struggling to add it to my current project: https://www.experts-exchange.com/questions/23286908/Downloaded-files-using-TIdHTTP-INDY-10.html

Here is my current project code:
unit uOxideModInstaller;

interface

uses
  Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants,
  System.Classes, Vcl.Graphics,
  Vcl.Controls, Vcl.Forms, Vcl.Dialogs, Vcl.ExtCtrls, Vcl.ComCtrls,
  Vcl.StdCtrls, IdBaseComponent, IdComponent,
  IdTCPConnection, IdTCPClient, IdHTTP, System.Zip;

type

  TDownload = class;

  Tfrmoxidemodinstaller = class(TForm)
    lbl1: TLabel;
    pb1: TProgressBar;
    btn1: TButton;
    btn2: TButton;
    lblstatus: TLabel;
    procedure btn2Click(Sender: TObject);
    procedure btn1Click(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }
  end;

  TDownload = class(TThread)
  private
    httpclient: TIdHTTP;
    url: string;
    filename: string;
    maxprogressbar: integer;
    progressbarstatus: integer;
    procedure ExtractZip(ZipFile: string; ExtractPath: string);
    procedure idhttp1Work(ASender: TObject; AWorkMode: TWorkMode;
      AWorkCount: Int64);
    procedure idhttp1WorkBegin(ASender: TObject; AWorkMode: TWorkMode;
      AWorkCountMax: Int64);
    procedure UpdateProgressBar;
    procedure SetMaxProgressBar;
  protected
    procedure Execute; override;
  public
    constructor Create(CreateSuspended: boolean; aurl, afilename: string);
    destructor Destroy; override;
  end;

var
  frmoxidemodinstaller: Tfrmoxidemodinstaller;

implementation

{$R *.dfm}
{ Thread }

constructor TDownload.Create(CreateSuspended: boolean; aurl, afilename: string);
begin
  inherited Create(CreateSuspended);
  httpclient := TIdHTTP.Create(nil);
  httpclient.OnWorkBegin := idhttp1WorkBegin;
  httpclient.OnWork := idhttp1Work;
  url := aurl;
  filename := afilename;
end;

procedure TDownload.idhttp1Work(ASender: TObject; AWorkMode: TWorkMode;
  AWorkCount: Int64);
begin
  progressbarstatus := AWorkCount;
  Queue(UpdateProgressBar);

end;

procedure TDownload.idhttp1WorkBegin(ASender: TObject; AWorkMode: TWorkMode;
  AWorkCountMax: Int64);
begin
  maxprogressbar := AWorkCountMax;
  Queue(SetMaxProgressBar);
end;

procedure TDownload.Execute;
var
  Stream: TMemoryStream;
begin
  Stream := TMemoryStream.Create;
  try
    httpclient.Get(url, Stream);
    Stream.SaveToFile(filename);
  finally
    Stream.Free;
  end;
end;

procedure TDownload.UpdateProgressBar;
var
  ZipFile: string;
begin
  frmoxidemodinstaller.pb1.Position := progressbarstatus;
  frmoxidemodinstaller.lblstatus.Caption := 'Downloading...';

  if frmoxidemodinstaller.pb1.Position = frmoxidemodinstaller.pb1.Max then
  begin
    frmoxidemodinstaller.lblstatus.Caption := 'Done Downloading. Installing...';
    Sleep(2000);
    ExtractZip('oxide.zip', GetCurrentDir);
  end;
end;

procedure TDownload.SetMaxProgressBar;
begin
  frmoxidemodinstaller.pb1.Max := maxprogressbar;
end;

destructor TDownload.Destroy;
begin
  FreeAndNil(httpclient);
  inherited Destroy;
end;

{ TForm1 }

procedure TDownload.ExtractZip(ZipFile, ExtractPath: string);
begin
  if TZipFile.IsValid(ZipFile) then
  begin
    TZipFile.ExtractZipFile(ZipFile, ExtractPath);
    frmoxidemodinstaller.lblstatus.Caption := 'Oxide Installed!';
    DeleteFile(ZipFile);
  end
  else
  begin
    ShowMessage('Error installing oxide!');
    frmoxidemodinstaller.lblstatus.Caption := 'Error Installing Oxide!';
  end;
end;

procedure Tfrmoxidemodinstaller.btn1Click(Sender: TObject);
var
  DownloadThread: TDownload;
  link: string;
begin
  link := 'http://41.185.91.51/RSM/Oxide-Rust.zip';
  DownloadThread := TDownload.Create(true, link, 'oxide.zip');
  DownloadThread.FreeOnTerminate := true;
  DownloadThread.Start;
end;

procedure Tfrmoxidemodinstaller.btn2Click(Sender: TObject);
begin
  Close;
end;

end.

Open in new window

Avatar of Kimputer
Kimputer

The two URL's differ in behavior:

http://41.185.91.51/RSM/Oxide-Rust.zip
is a full DIRECT LINK to the file

https://bintray.com/oxidemod/builds/download_file?file_path=Oxide-Rust.zip
is a request and after that you will get the DIRECT LINK.
Apparently TldHTTP isn't smart enough to handle it in one go (or probably needs another few more lines of code), so the easiest way to solve it for now is, have the direct link in your code. Not the request.

https://dl.bintray.com/oxidemod/builds/Oxide-Rust.zip
You have to work with the SSL protocol (the url starts with https)

Add IdSSLOpenSSL to the uses clause

Modify your TDownload Class as Follow
TDownload = class(TThread)
  private
    httpclient: TIdHTTP;
    IOHndl: TIdSSLIOHandlerSocketOpenSSL; //this is the ssl handler 
    url: string;
    filename: string;
    maxprogressbar: integer;
    progressbarstatus: integer;
    procedure ExtractZip(ZipFile: string; ExtractPath: string);
    procedure idhttp1Work(ASender: TObject; AWorkMode: TWorkMode; AWorkCount: Int64);
    procedure idhttp1WorkBegin(ASender: TObject; AWorkMode: TWorkMode; AWorkCountMax: Int64);
    procedure UpdateProgressBar;
    procedure SetMaxProgressBar;
  protected
    procedure Execute; override;
  public
    constructor Create(CreateSuspended: boolean; aurl, afilename: string);
    destructor Destroy; override;
  end;
constructor TDownload.Create(CreateSuspended: boolean; aurl, afilename: string);
begin
  inherited Create(CreateSuspended);
  httpclient := TIdHTTP.Create(nil);
  IOHndl := TIdSSLIOHandlerSocketOpenSSL.Create(nil);
  httpclient.Request.BasicAuthentication := True;
  httpclient.HandleRedirects := True;
  httpclient.IOHandler := IOHndl;
  httpclient.ReadTimeout := 30000;
  httpclient.OnWorkBegin := idhttp1WorkBegin;
  httpclient.OnWork := idhttp1Work;
  url := aurl;
  filename := afilename;
end;

procedure TDownload.idhttp1Work(ASender: TObject; AWorkMode: TWorkMode; AWorkCount: Int64);
begin
  progressbarstatus := AWorkCount;
  Queue(UpdateProgressBar);
end;

procedure TDownload.idhttp1WorkBegin(ASender: TObject; AWorkMode: TWorkMode; AWorkCountMax: Int64);
begin
  maxprogressbar := AWorkCountMax;
  Queue(SetMaxProgressBar);
end;

procedure TDownload.Execute;
var
  Stream: TMemoryStream;
begin
  Stream := TMemoryStream.Create;
  try
    httpclient.Get(url, Stream);
    Stream.SaveToFile(filename);
  finally
    Stream.Free;
  end;
end;

procedure TDownload.UpdateProgressBar;
var
  ZipFile: string;
begin
  frmoxidemodinstaller.pb1.Position := progressbarstatus;
  frmoxidemodinstaller.lblstatus.Caption := 'Downloading...';
  if frmoxidemodinstaller.pb1.Position = frmoxidemodinstaller.pb1.Max then
  begin
    frmoxidemodinstaller.lblstatus.Caption := 'Done Downloading. Installing...';
    Sleep(2000);
    ExtractZip('oxide.zip', GetCurrentDir);
  end;
end;

procedure TDownload.SetMaxProgressBar;
begin
  frmoxidemodinstaller.pb1.Max := maxprogressbar;
end;

destructor TDownload.Destroy;
begin
  FreeAndNil(IOHndl);
  FreeAndNil(httpclient);
  inherited Destroy;
end;
{ TForm1 }

procedure TDownload.ExtractZip(ZipFile, ExtractPath: string);
begin
  if TZipFile.IsValid(ZipFile) then
  begin
    TZipFile.ExtractZipFile(ZipFile, ExtractPath);
    frmoxidemodinstaller.lblstatus.Caption := 'Oxide Installed!';
    DeleteFile(ZipFile);
  end
  else
  begin
    ShowMessage('Error installing oxide!');
    frmoxidemodinstaller.lblstatus.Caption := 'Error Installing Oxide!';
  end;
end;

Open in new window

Avatar of Adriaan Boshoff

ASKER

This direct link doesnt work: https://dl.bintray.com/oxidemod/builds/Oxide-Rust.zip
Even after adding @Ferruccio Accalai answere

I have attached the form used in the project.
You can access it by creating a new vcl form app and adding this to the existing project
project.zip
var
  DownloadThread: TDownload;
  link: string;
begin
  link := 'https://bintray.com/oxidemod/builds/download_file?file_path=Oxide-Rust.zip';
  DownloadThread := TDownload.Create(True, link, 'oxide.zip');
  DownloadThread.FreeOnTerminate := True;
  DownloadThread.Start;
end;

Open in new window

For me this code is working perfect with the TDownload class posted above
ASKER CERTIFIED SOLUTION
Avatar of Ferruccio Accalai
Ferruccio Accalai
Flag of Italy image

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial