Solved

download a file from a website

Posted on 2004-10-19
16
780 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:EddieShipman
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
 

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:EddieShipman
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
How to run any project with ease

Manage projects of all sizes how you want. Great for personal to-do lists, project milestones, team priorities and launch plans.
- Combine task lists, docs, spreadsheets, and chat in one
- View and edit from mobile/offline
- Cut down on emails

 
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 100 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

How to run any project with ease

Manage projects of all sizes how you want. Great for personal to-do lists, project milestones, team priorities and launch plans.
- Combine task lists, docs, spreadsheets, and chat in one
- View and edit from mobile/offline
- Cut down on emails

Join & Write a Comment

Suggested Solutions

Title # Comments Views Activity
TcomboBox uninverted item 3 44
Help to pass a value through a function 2 64
ddeman not working in activex 3 79
Convert Jpg /PNG To GIF 5 103
Introduction The parallel port is a very commonly known port, it was widely used to connect a printer to the PC, if you look at the back of your computer, for those who don't have newer computers, there will be a port with 25 pins and a small print…
Introduction I have seen many questions in this Delphi topic area where queries in threads are needed or suggested. I know bumped into a similar need. This article will address some of the concepts when dealing with a multithreaded delphi database…
Excel styles will make formatting consistent and let you apply and change formatting faster. In this tutorial, you'll learn how to use Excel's built-in styles, how to modify styles, and how to create your own. You'll also learn how to use your custo…
In this seventh video of the Xpdf series, we discuss and demonstrate the PDFfonts utility, which lists all the fonts used in a PDF file. It does this via a command line interface, making it suitable for use in programs, scripts, batch files — any pl…

757 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

Need Help in Real-Time?

Connect with top rated Experts

23 Experts available now in Live!

Get 1:1 Help Now