[Last Call] Learn how to a build a cloud-first strategyRegister Now

x
?
Solved

download a file from a website

Posted on 2004-10-19
16
Medium Priority
?
794 Views
Last Modified: 2011-10-03
I want to download a file from a website let's say x.com/files/down.zip (around 5mb) to my computer but with this options.
1. to get the size of the file
2. to start download, stop it and resume it
3. to show a progressbar and how much was downloaded


I've tried using idhttp from indy 9.0 but when downloading the program does,nt respond until finished and i didn't find a way to make the above steps.

I try to make a small installer and download a file from a site and opening.

Any help would be apreciated

dia21
0
Comment
Question by:dia21
  • 6
  • 5
  • 2
  • +2
16 Comments
 
LVL 26

Expert Comment

by:Eddie Shipman
ID: 12351364
Use ICS as it uses non-blocking sockets unlike Indy.

http://www.overbyte.be/frame_index.html
0
 
LVL 14

Expert Comment

by:DragonSlayer
ID: 12351598
Check out this sample for resuming download (and multi-segment downloads using multiple threads) http://codecentral.borland.com/codecentral/ccweb.exe/download?id=17604

0
 

Author Comment

by:dia21
ID: 12352688
EddieShipman i don't want to use a shareware component

DragonSlayer i can't download it or see what is there
0
Technology Partners: We Want Your Opinion!

We value your feedback.

Take our survey and automatically be enter to win anyone of the following:
Yeti Cooler, Amazon eGift Card, and Movie eGift Card!

 

Author Comment

by:dia21
ID: 12352737
DragonSlayer please give me another location or the code because i get this "Internal Application Error" when visiting your site
0
 
LVL 1

Expert Comment

by:vacerose
ID: 12354962
Indy Blocking Workaround
If you look on the "Indy Misc" component tab there is a component called TIdAntifreeze.  Add this component to your app and the the "OnlyWhenIdle" property to false.  This will cause Indy to call ProcessMessages during the download allowing you to call the http component "Disconnect" method when a button is clicked.  You should wrap the Get method in an exception handler to deal with the disconnect gracefully.

Indy HTTP progress
The indy HTTP component has 2 events you need for the progress display.  In OnWorkBegin save the AWorkCountMax parameter to a global variable, this is the total byte count. I prefer to assign it to the Tag property of the http component.  In OnWork, the AWorkCount parameter is the number of bytes downloaded so far.

Indy Resume
Sorry I can't help you with the resume. I'm not sure it is possible with Indy 9
0
 
LVL 14

Expert Comment

by:DragonSlayer
ID: 12355158
0
 
LVL 26

Expert Comment

by:Eddie Shipman
ID: 12357949
Pardon me but ICS is FREE, just like Indy. Did you EVEN check it out?
0
 

Author Comment

by:dia21
ID: 12361594
EddieShipman you're right. I did checked the link but i saw the purchase link and i thought that is shareware, sorry:)
I downloaded now and i'll take a look
0
 
LVL 17

Expert Comment

by:TheRealLoki
ID: 12361845
There are a number of ways to do this, below is a simple code snippit that will give you an idea of how to do this. Make sure to add ShellApi, and UrlMon to your uses clause.

function DownLoadInternetFile(Source, Dest : String): Boolean;
begin
  try
    Result := URLDownloadToFile(nil,PChar(Source),PChar(Dest),0,nil) = 0
  except
    Result := False;
  end;
end;

procedure TForm1.Button1Click(Sender: TObject);
var
  SourceString, DestinationString: string;
begin
//File location on the Internet.
  SourceString := 'http://www.borland.com/images/homepage/del6homemural.gif';
//File destination.
  DestinationString := 'C:Tempdel6homemural.gif';

  if DownLoadInternetFile(SourceString, DestinationString) then
//This will display the file from your browser.
    ShellExecute(Application.Handle, PChar('Open'), PChar(DestinationString), PChar(''), nil, SW_NORMAL)
  else
    ShowMessage('Error during Download ' + SourceString);
end;
0
 
LVL 17

Accepted Solution

by:
TheRealLoki earned 300 total points
ID: 12362202
here's a real quick demo I wrote for you, showing the download and progress


unit Unit1;

interface

uses
  Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
  StdCtrls, ComCtrls, IdBaseComponent, IdComponent, IdTCPConnection,
  IdTCPClient, IdHTTP, IdAntiFreezeBase, IdAntiFreeze;
// By }-=Loki=-{ lokiwashere@yahoo.co.nz
type
  TForm1 = class(TForm)
    IdHTTP1: TIdHTTP;
    ProgressBar1: TProgressBar;
    Button1: TButton;
    eFilename: TEdit;
    Label2: TLabel;
    IdAntiFreeze1: TIdAntiFreeze;
    procedure Button1Click(Sender: TObject);
    procedure IdHTTP1WorkBegin(Sender: TObject; AWorkMode: TWorkMode;
      const AWorkCountMax: Integer);
    procedure IdHTTP1Work(Sender: TObject; AWorkMode: TWorkMode;
      const AWorkCount: Integer);
  private
    { Private declarations }
    TotalFilesize: Integer;
    function GetFilenameFromAddress(s: string): string;
  public
    { Public declarations }
  end;

var
  Form1: TForm1;

IMPLEMENTATION

{$R *.DFM}

function TForm1.GetFilenameFromAddress(s: string): string;
    begin
        S := StringReplace(S, '/', '\', [rfReplaceAll]);
        result := ExtractFileName(S);
    end;

procedure TForm1.Button1Click(Sender: TObject);
    var
        fs: TStream;
    begin
        fs := TFileStream.Create(ExtractFilePath(Paramstr(0)) + GetFilenameFromAddress(eFilename.Text), fmCreate);
        try
            IdHTTP1.Get(eFilename.text, fs);
        finally
            fs.free;
        end;
        ShowMessage('completed');
    end;

procedure TForm1.IdHTTP1WorkBegin(Sender: TObject; AWorkMode: TWorkMode;
    const AWorkCountMax: Integer);
    begin
        ProgressBar1.Max := AWorkCountMax;
        ProgressBar1.Position := 0;
    end;

procedure TForm1.IdHTTP1Work(Sender: TObject; AWorkMode: TWorkMode;
    const AWorkCount: Integer);
    begin
        ProgressBar1.StepBy(AWorkCOunt);
        ProgressBar1.Repaint;
    end;

end.


/// FORM FOLLOWS

object Form1: TForm1
  Left = 274
  Top = 168
  Width = 392
  Height = 191
  Caption = 'Form1'
  Color = clBtnFace
  Font.Charset = DEFAULT_CHARSET
  Font.Color = clWindowText
  Font.Height = -11
  Font.Name = 'MS Sans Serif'
  Font.Style = []
  OldCreateOrder = False
  PixelsPerInch = 96
  TextHeight = 13
  object Label2: TLabel
    Left = 24
    Top = 24
    Width = 42
    Height = 13
    Caption = 'Filename'
  end
  object ProgressBar1: TProgressBar
    Left = 8
    Top = 112
    Width = 321
    Height = 16
    Min = 0
    Max = 100
    TabOrder = 0
  end
  object Button1: TButton
    Left = 8
    Top = 80
    Width = 75
    Height = 25
    Caption = 'Button1'
    TabOrder = 1
    OnClick = Button1Click
  end
  object eFilename: TEdit
    Left = 96
    Top = 16
    Width = 241
    Height = 21
    TabOrder = 2
    Text = 'http://torry.net/images/h2-1.gif'
  end
  object IdHTTP1: TIdHTTP
    MaxLineAction = maException
    OnWork = IdHTTP1Work
    OnWorkBegin = IdHTTP1WorkBegin
    AllowCookies = True
    ProxyParams.BasicAuthentication = False
    ProxyParams.ProxyPort = 0
    Request.ContentLength = -1
    Request.ContentRangeEnd = 0
    Request.ContentRangeStart = 0
    Request.ContentType = 'text/html'
    Request.Accept = 'text/html, */*'
    Request.BasicAuthentication = False
    Request.UserAgent = 'Mozilla/3.0 (compatible; Indy Library)'
    HTTPOptions = [hoForceEncodeParams]
    Left = 160
    Top = 72
  end
  object IdAntiFreeze1: TIdAntiFreeze
    Left = 200
    Top = 72
  end
end
0
 
LVL 17

Expert Comment

by:TheRealLoki
ID: 12362238
I can show you how to resume by using Francois Piette's ICS, it's as simple as
    httpcli1.ContentRangeBegin := IntToStr(httpcli1.ContentLength - 100);
    httpcli1.ContentRangeBegin := IntToStr(httpcli1.ContentLength);
    httpcli1.Get;
(this would get the last 100 bytes)
and the progress is pretty straight forward. You should be able to suss it out from the demos
0
 

Author Comment

by:dia21
ID: 12364069
TheRealLoki
the resume it's working but it stil downloads from the server the entire server and it writes on my computer from the last 100 bytes. I want that download from where it stoped. In the way from your code it's the same thing as if i would download it again. have any sugestions an how to fix this?

as the progress i didn't find in the demos with ics
0
 
LVL 17

Expert Comment

by:TheRealLoki
ID: 12365207
to resume, what you'd do is open the partial file, get the "partialfilesize"
(e.g. open it as a TFileStream and check the size, plenty of examples of that elsewhere)
and read (append) from there

e.g. ContentRangeBegin := partialfilesize

Update the progress bar in the OnDocData event, or the OnSendData event
0
 

Author Comment

by:dia21
ID: 12374061
It still doesn't work the resume. The ics downloads the entire file and it updates my file when it arrives at the corrct size.
Here is the code that i use maybe i do something wrong.

procedure TForm1.Button1Click(Sender: TObject);

function swapSlash(text:String):String;
begin
  text := StringReplace(text, '/', '\', [rfReplaceAll]);
        result := ExtractFileName(text);
end;

var result:String;
    ms:TFileStream;
    exists:boolean;
begin
    button2.Enabled:=True;
    Debuglistbox.Items.Clear;
    result:=ExtractFilepath(ParamStr(0))+ExtractFilename(swapslash(url));
    httpcli1.URL:=url;
    if Fileexists(result) then
    begin
        exists:=True;
       httpcli1.RcvdStream:=TFileStream.Create(result,fmOpenWrite);
    end
         else begin exists:=False;
             httpcli1.RcvdStream:=TFileStream.Create(result,fmCreate);
            end;
    Button1.Enabled:=False;
    Debuglistbox.Items.Add('Connecting...');
    try
      try
      if exists then
        begin
          Debuglistbox.Items.Add('File already exists. Resuming ...');
          httpcli1.ContentRangeBegin:=IntToStr(httpcli1.RcvdStream.Size);

        end;
        progressbar1.Max:=1163722;
        httpcli1.Get;
        Label1.Caption:='Received: '+ IntToStr(ceil(httpcli1.RcvdStream.Size/1024))+ ' kb';
      except
      on E: EHttpException do begin
                Label1.Caption := 'Failed : ' +
                                     IntToStr(HttpCli1.StatusCode) + ' ' +
                                     HttpCli1.ReasonPhrase;;
            end
            else
                raise;
        end;
    finally
   Button1.Enabled:=True;
   button2.Enabled:=False;
   label1.Caption:='';
   HttpCli1.RcvdStream.Destroy;
   HttpCli1.RcvdStream := nil;
end;
end;
0
 
LVL 17

Expert Comment

by:TheRealLoki
ID: 12374190
The _server_ has to support resumes, If it does not, then yes, it will download the entire file
0
 

Author Comment

by:dia21
ID: 12374410
but the code is correct?
0

Featured Post

Free Tool: SSL Checker

Scans your site and returns information about your SSL implementation and certificate. Helpful for debugging and validating your SSL configuration.

One of a set of tools we are providing to everyone as a way of saying thank you for being a part of the community.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

Introduction Raise your hands if you were as upset with FireMonkey as I was when I discovered that there was no TListview.  I use TListView in almost all of my applications I've written, and I was not going to compromise by resorting to TStringGrid…
In my programming career I have only very rarely run into situations where operator overloading would be of any use in my work.  Normally those situations involved math with either overly large numbers (hundreds of thousands of digits or accuracy re…
We’ve all felt that sense of false security before—locking down external access to a database or component and feeling like we’ve done all we need to do to secure company data. But that feeling is fleeting. Attacks these days can happen in many w…
Is your data getting by on basic protection measures? In today’s climate of debilitating malware and ransomware—like WannaCry—that may not be enough. You need to establish more than basics, like a recovery plan that protects both data and endpoints.…
Suggested Courses

834 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question