I am using the TDownloadURL to download a specified URL to disk.
I want to give the user feedback on the progress of each URL I download
using TDownloadURL.
When I assign the OnDowload Progress procedure to the TDownloadURL's
OnProgress event it gives me an "Invalid Enum Value" error.
Here is my code, please help:
function TfrmURLS.DownloadHTML(const sURL,
sLocalFileName: string): Boolean;
begin
Result:=True;
with TDownLoadURL.Create(nil) do
try
URL:=sURL;
Filename:=sLocalFileName;
OnDownloadProgress := URL_OnDownloadProgress;
try
ExecuteTarget(nil);
except
Result:=False
end;
finally
Free;
end;
end;
procedure TfrmURLS.URL_OnDownloadProgress;
begin
Label1.Caption := StatusText;
pbarCurrentProgress.Max := ProgressMax;
pbarCurrentProgress.Position := Progress;
end;
Function DownloadHTML(const sURL, sLocalFileName:string): Boolean;
Procedure URL_OnDownloadProgress(Sender :TDownloadURL; Progress,
ProgressMax :Cardinal;
StatusCode :TURLDownLoadStatus; StatusText :String; var Cancel
:Boolean);
Thanks alot
> Procedure URL_OnDownloadProgress(Sender :TDownloadURL; Progress,
> ProgressMax :Cardinal;
> StatusCode :TURLDownLoadStatus; StatusText :String; var Cancel
> :Boolean);
All of those parameters are missing entirely from your actual implementation
code that you showed:
procedure TfrmURLS.URL_OnDownloadProgress; // <-- NO PARAMETERS
begin
Label1.Caption := StatusText;
pbarCurrentProgress.Max := ProgressMax;
pbarCurrentProgress.Position := Progress;
end;
Gambit
Even with or without parameters it is giving me the error.
Any other suggestion?
> Even with or without parameters it is giving me the error.
What is the EXACT error message? Is it a compile-time or run-time error?
Gambit
Error message:
"Project Project1.exe raised exception class Exception with message
'Invalid Enum Value'. Process stopped. User Step or Run to continue."
Thanks
> Is is a runtime error as soon as the TDownloadUrl are triggered.
If you are actually running the program, then it is a runtime error.
> "Project Project1.exe raised exception class Exception with message
> 'Invalid Enum Value'. Process stopped. User Step or Run to continue."
There is only one way for that error to be produced by TDownloadURL.
Internally, TDownloadURL uses the URLMonDownloadToFile() function, providing
itself as the IBindStatusCallBack interface. Inside of the progress
tracking, TDownloadURL tries to convert API status codes into
TURLDownloadStatus enum values. The error you are seeing is thrown when the
API reports a status code that TDownloadURL does not recognize.
Which OS are you running under? There are currently 27 API status codes
that TDownloadURL does not recognize. That suggests to me that TDownloadURL
was written for an older version of the API and has not been updated to
support the latest version. In which case, you will probably have to avoid
using TDownloadURL altogether and just download the file manually.
Gambit
I am running Windows 2000 Pro myself.
Thanks for the help so far,
> I would like to have it running on all Windows platforms:
> Win98,NT,XP,2000,2003
Like I said before, TDownloadURL does not support what your machine is
actuall producing for progress statuses, so you will not be able to use it
for all systems. I recommend that you get yourself a HTTP component instead
and just download the file manually. Indy (http://www.indyproject.org) and
ICS (http://overbyte.be) both have HTTP client components, for instance.
Gambit
How must you use idHTTP correctly and programming friendly to give reliable
results?
Thanks
Delphi 6 only defined 25 enum values for BIND_STATUS but Delphi 7 defines all 55 enum
values.
Why don't you just implement the IBindStatusCallback interface on your own custom object.
It is not that difficult and the TDownLoadURL code is a good starting point but it does
not implement several other call backs that can easily be handled and make your user
interface a lot nicer.
Dennis Passmore
Ultimate Software, Inc.
1) Can you please refer me to some example code or reading?
2) Cant I do error checking and limited Delphi 6 to handle only the known
25?
Thanks again,
> 2) Cant I do error checking and limited Delphi 6 to handle
> only the known 25?
No, because the error is happening inside of TDownloadURL's internals, where
you can't get to the problem. As Dennis mentioned, the only way to make D6
work is to implement your own download code instead of using the native
TDownloadURL.
Gambit
2) Is there a good example or component that I can use if I want to LOOP
through hundreds of web pages and download the pages without getting funny
errors and problems.
I need a reliable component/method of downloading alot of urls?
If you believe idHTTP can do the job what precautions must I take and what
kind of cleanup must I do in order to get the maximum URLs to download???
Thanks
> I have tried idHTTP from Indy but out of a list of 100 URL at
> least 13 wont download
You need to provide specific details if you want the issue to be addressed.
> and with TDownloadURL just 1 or 2 URLs of 100 wont download
> and if I try to open these 2 URLs in Internet Explorer they are also
> unavailable
Then the URLs themselves are either messed up to begin with, or else the
HTTP servers are filtering out Microsoft's browser.
Gambit
> 1) A very common error on idHTTP is: "Connection Closed Gracefully".
That is not usually an error. That is used by Indy for internal purposes.
That exception does not escape into the user code unless the socket really
is in an error condition.
> 2) Is there a good example or component that I can use if I want
> to LOOP through hundreds of web pages and download the pages
> without getting funny errors and problems.
TIdHTTP handles that just fine. Just call Get() in your loop as expected.
> I need a reliable component/method of downloading alot of urls?
TIdHTTP is reliable.
> If you believe idHTTP can do the job what precautions must I take
> and what kind of cleanup must I do in order to get the maximum
> URLs to download???
There is no cleanup needed. Everything is handled internally.
Gambit
I also receive this error alot:
"Project Project1.exe raised exception class EIdHTTPProtocolException
with message 'HTTP/1.1 302 Object moved'.
What is this?
Thanks alot!
How can I ensure that the URL is fine for idHTTP?
What does the PathEncode() and UrlEncode() do?
Which one should I use to make sure my URL is in a undestandable format do
use in TIdHTTP.Get()?
Thanks
> I think that part of my problem is that idHTTP interperet
> the URL incorrectly, maybe there is spaces in the URL
> or unknow format.
You are not supposed to be including spaces in the URL to begin with.
Gambit
I read something about the "%20" represents a space within the browsers but
idHTTP dont recognise that.
Some URL's might even be wrong so I need to take care off Error Handling and
preventing idHTTP to hang as it is doing now when an URL is not active.
Please while on the topic:
1) How can I also take care of the user interface not to freeze while
idHTTP is Getting the URLs?
2) Can I set a TimeOut on idHTTP and what TimeOut value would you
suggest?
Sorry for all these questions but you surely help alot
> I am not downloading my own URL but those from a list provided.
Then your list is wrong. Spaces are not valid in URLs.
> I read something about the "%20" represents a space within
> the browsers but idHTTP dont recognise that.
All spaces must be encoded as %20 prior to requesting the URL, yes. You are
supposed to encode the spaces as %20 PRIOR TO calling Get(), Post(), Head(),
etc.
> Some URL's might even be wrong so I need to take care off Error
> Handling and preventing idHTTP to hang as it is doing now when an
> URL is not active.
If a URL is not valid, TIdHTTP will either 1) fail to connect altogether, or
2) the HTTP server will report an error. Hanging should not be occuring.
> How can I also take care of the user interface not to freeze while
> idHTTP is Getting the URLs?
By not making the requests in the context of the main thread to begin with.
Use worker threads instead.
> Can I set a TimeOut on idHTTP
Have you looked at the ConnectTimeout and ReadTimeout properties yet?
Gambit
This is my code:
procedure TfrmURLS.IdHTTPWork(ASender: TObject; AWorkMode: TWorkMode;
AWorkCount: Integer);
begin
pbarCurrentProgress.Position := AWorkCount;
end;
procedure TfrmURLS.IdHTTPStatus(ASender: TObject; const AStatus: TIdStatus;
const AStatusText: String);
begin
lblStatus.Caption := AStatusText;
lblStatus.Update;
end;
procedure TfrmURLS.IdHTTPWorkBegin(ASender: TObject; AWorkMode: TWorkMode;
AWorkCountMax: Integer);
begin
pbarCurrentProgress.Position := 0;
pbarCurrentProgress.Max := AWorkCountMax;
end;
procedure TfrmURLS.IdHTTPWorkEnd(ASender: TObject; AWorkMode: TWorkMode);
begin
pbarCurrentProgress.Position := 0;
end;
> If I try to update my progressbar on the Begin-, End and Work
> events of the idHTTP then I receive an EDiv by Zero error.
You are not taking into account that sometimes the AWorkCountMax value of
the OnWorkBegin event can be 0, meaning that TIdHTTP does not know ahead of
time how much data is going to be received during the download. It is the
server's responsibility to specify how much data it is going to be sending,
but depending on the nature of the data it is not always possible to report
that accurately.
Gambit
http://www.dpassmore.com/wdata/MyStreamLibEx.zip
file name: MyStreamLibEx.zip