How to download files using data from tstring? Delphi and THttpGet

682 views Asked by At

I have two string lists: name (contains file names), url (contains file urls). I would like to download all neccessary files using THttpget in one loop, with a progress bar:

for d:=0 to numberOfDownloads-1 do
begin
HTTPGet2.URL:=url[d];
HTTPGet2.FileName:=name[d];
HTTPGet2.GetFile;
end;

It works, but it downloads only one file - first on the string list. How can I do that? numberOfDownloads - number of items in the stringlist name.

2

There are 2 answers

4
PA. On BEST ANSWER

HTTPGet downloads a file asynchronously, by creating a secondary thread and notifying thru standard events.

So, in your case, when you iterate over the loop and get to the second file to download, the HTTPGet2 instance is still busy processing the previous download.

One simple way to overcome this is to create an array of HTTPGet instances... something like this...

 var HTTPGets: array of THttpGet;
   ...
 setlength(HTTPGets,numberOfDownloads);
 ...
 for d:=0 to numberOfDownloads-1 do
   begin
    HTTPGets[d]:=THttpGet.Create(...);
    HTTPGets[d].URL:=...;
     ...
    HTTPGets[d].GetFile;
   end;
 end.

and to get notified of the finalization events, you need to create your own OnDoneFile and set it...

   HTTPGets[d].OnDoneFile:=HTTPGetOnDone;
0
RobertFrank On

Approximate code below excerpted from a working version that uses Indy components. You'll need to fill in some gaps to make it compile, but it should give you the idea. For multiple files, either call repeatedly as your loop does, or call with a list of filenames, and have the code below loop internally...

type
  TDownloadResult = (DRSuccess, DRHostNotFound, DRFileNotFound, DRUserCancelled, DROther);

function TDownload.Download(const aSourceURL: String;
                            const aDestFileName: String;
                            const aShowProgress: Boolean;
                            out   aDownloadResult: TDownloadResult;
                            out   aErrm: String): boolean;
var
  Stream: TMemoryStream;
  IDAntiFreeze: TIDAntiFreeze;
begin
  Screen.Cursor := crHourGlass;
  aDownloadResult := DROther;
  aErrm :='Unexpected web error.';
  fShowProgress := aShowProgress;
  if fShowProgress then
    begin
      frmProgressBar := TfrmProgressBar.Create(Application.MainForm);
      frmProgressBar.SetMessage1'Downloading File...');
      frmProgressBar.Show;
    end;

  fIDHTTP := TIDHTTP.Create;
  fIDHTTP.HandleRedirects := TRUE;
  fIDHTTP.AllowCookies := FALSE;
  fIDHTTP.Request.UserAgent := 'Mozilla/4.0';
  fIDHTTP.Request.Connection := 'Keep-Alive';
  fIDHTTP.Request.ProxyConnection := 'Keep-Alive';
  fIDHTTP.Request.CacheControl := 'no-cache';
  fIDHTTP.OnWork := IdHTTP1Work;
  fIDHTTP.OnWorkBegin := IdHTTP1WorkBegin;
  IDAntiFreeze := TIDAntiFreeze.Create;

  Stream := TMemoryStream.Create;
  try
    try
      fIDHTTP.Get(aSourceURL, Stream);
      if FileExists(aDestFileName) then
        DeleteFile(PWideChar(aDestFileName));
      Stream.SaveToFile(aDestFileName);
      Result := TRUE;
      aDownloadResult :=drSuccess;
    except
      On E: Exception do
        begin
          Result := FALSE;
          aErrm := E.Message + ' (' + IntToStr(fIDHTTP.ResponseCode) + ')';
          if fShowProgress AND fShowProgress AND frmProgressBar.Cancelled then
            aDownloadResult := DRUserCancelled
          else if (fIDHTTP.ResponseCode = 404) OR (fIDHTTP.ResponseCode = 302) then
            aDownloadResult := DRFileNotFound
          else if (FIDHTTP.ResponseCode = -1) then
            aDownloadResult := DRHostNotFound
          else
            aDownloadResult := DROther;
        end;
    end;
  finally
    Screen.Cursor := crDefault;
    Stream.Free;
    IDAntiFreeze.Free;
    fIDHTTP.Free;
    if fShowProgress then
      frmProgressBar.Free;
  end;
end;  { Download }


procedure TDownload.IdHTTP1Work(ASender: TObject; AWorkMode: TWorkMode; AWorkCount: Int64);
begin
  if fShowProgress AND frmProgressBar.Cancelled then
     raise EUserCancelled.Create('');
  if fShowProgress AND (fMaxWork > 0) then
    frmProgressBar.SetPosition(AWorkCount, GetMsg(MSG_PERCENT_COMPLETE, IntToStr( Round(AWorkCount/fMaxWork * 100)) + '%'));
end; { IdHTTP1Work }

procedure TDownload.IdHTTP1WorkBegin(ASender: TObject; AWorkMode: TWorkMode; AWorkCountMax: Int64);
begin
  fMaxWork := AWorkCountMax;
  if fShowProgress then
    frmProgressBar.SetMinMax(0, fMaxWork);
end; { IdHTTP1WorkBegin }

Sample use:

procedure TForm1.Button1Click(Sender: TObject);
var
  Download: TDownload;
  Errm: String;
  DownloadResult: TDownloadResult;
begin
  Download := TDownload.Create;
  if NOT TDownload.Download( 'http://www.URL.com/filename.ext',
                             'c:\junk\au.mpg', TRUE, DownloadResult, Errm) then
    begin
      case DownloadResult of
         DRFileNotFound: ShowMessage ('File not found!!' + #13 + Errm);
         DRUserCancelled: ShowMessage ('Cancelled!');
         DrHostNotFound: ShowMessage ('Are you on line?');
         DrOther: ShowMessage ('Other: ' + Errm);
      else
        ShowMessage('huh?');
      end
    end
  else
    ShowMessage ('Download succeeded!');
end;