How to download files using data from tstring? Delphi and THttpGet
-
19-04-2021 - |
Frage
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.
Lösung
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;
Andere Tipps
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;