JustinWillis
asked on
Retrieve content size using WinInet
Hiya, I am trying to use the following code found on EE but I cannot get it to work and it is hopefully something simple I have messed up!
The FileSize retrieved does not seem to be accurate, for example I tried to get the size of http://www.google.co.uk/search?hl=en&safe=off&q=test&meta= but it said it was 1359176 bytes?? am i missing something here?
uses WinInet
procedure TForm1.Button2Click(Sender : TObject);
var
hSession: HINTERNET;
hService: HINTERNET;
FileSize: Longint;
dwSize, Reserved: DWORD;
buf: String;
begin
hSession := InternetOpen( 'MyApp', INTERNET_OPEN_TYPE_PRECONF IG, nil, nil, 0 );
if Assigned( hSession ) then
begin
hService := InternetOpenUrl(hSession, PChar(edit1.text), nil, 0, 0, 0);
if Assigned( hService ) then
begin
dwSize := sizeof(FileSize); //what does this do? FileSize isn't anything yet is it??
Reserved := 0;
HttpQueryInfo(hService, HTTP_QUERY_CONTENT_LENGTH or HTTP_QUERY_FLAG_NUMBER,
@FileSize, dwSize, Reserved); //get the size
buf := Format('FileSize:%d', [FileSize]); //convert to a string
form1.Memo1.Lines.Add( buf ); //add the size to TMemo
end;
InternetCloseHandle( hService );
end;
InternetCloseHandle( hSession );
end;
Thanks for any help, it's driving me mad, trying to avoid Indy which I was using previously as this seems to be faster.
Regards,
Justin Willis.
The FileSize retrieved does not seem to be accurate, for example I tried to get the size of http://www.google.co.uk/search?hl=en&safe=off&q=test&meta= but it said it was 1359176 bytes?? am i missing something here?
uses WinInet
procedure TForm1.Button2Click(Sender
var
hSession: HINTERNET;
hService: HINTERNET;
FileSize: Longint;
dwSize, Reserved: DWORD;
buf: String;
begin
hSession := InternetOpen( 'MyApp', INTERNET_OPEN_TYPE_PRECONF
if Assigned( hSession ) then
begin
hService := InternetOpenUrl(hSession, PChar(edit1.text), nil, 0, 0, 0);
if Assigned( hService ) then
begin
dwSize := sizeof(FileSize); //what does this do? FileSize isn't anything yet is it??
Reserved := 0;
HttpQueryInfo(hService, HTTP_QUERY_CONTENT_LENGTH or HTTP_QUERY_FLAG_NUMBER,
@FileSize, dwSize, Reserved); //get the size
buf := Format('FileSize:%d', [FileSize]); //convert to a string
form1.Memo1.Lines.Add( buf ); //add the size to TMemo
end;
InternetCloseHandle( hService );
end;
InternetCloseHandle( hSession );
end;
Thanks for any help, it's driving me mad, trying to avoid Indy which I was using previously as this seems to be faster.
Regards,
Justin Willis.
ASKER
And Again!
Your call to get the content length is failing and you aren't initializing FileSize.
That is why you get spurious results. Initialize FileSize to -1 and modify it like
this to catch the error:
if HttpQueryInfo(hService, HTTP_QUERY_CONTENT_LENGTH or HTTP_QUERY_FLAG_NUMBER,
@FileSize, dwSize, Reserved) then
begin
buf := Format('FileSize:%d', [FileSize]); //convert to a string
form1.Memo1.Lines.Add( buf ); //add the size to TMemo
end
else
begin
err := SysErrorMessage(GetLastErr or);
Memo1.Lines.Add(err);
end;
However, I was unable to get the error message, it came back blank for
error #317.
That is why you get spurious results. Initialize FileSize to -1 and modify it like
this to catch the error:
if HttpQueryInfo(hService, HTTP_QUERY_CONTENT_LENGTH or HTTP_QUERY_FLAG_NUMBER,
@FileSize, dwSize, Reserved) then
begin
buf := Format('FileSize:%d', [FileSize]); //convert to a string
form1.Memo1.Lines.Add( buf ); //add the size to TMemo
end
else
begin
err := SysErrorMessage(GetLastErr
Memo1.Lines.Add(err);
end;
However, I was unable to get the error message, it came back blank for
error #317.
Another thing is that I think you have to have an HTTPOpenRequest in order to retrieve the content length with HTTPQueryInfo
which you are not doing.
which you are not doing.
Well, I put my foot in my mouth, didn't I. You used code that I posted. I did however, find this from RLibby in another post:
"It is possible that the servers on these sites do not generate the "Content-Length:" header item. This is not a required header,
though most sites do return it."
It seems that that URL isn't returning that information to you and you are just out of luck there.
"It is possible that the servers on these sites do not generate the "Content-Length:" header item. This is not a required header,
though most sites do return it."
It seems that that URL isn't returning that information to you and you are just out of luck there.
ASKER
Ok thanks, I will give this a try tonight and let you know. It makes sense although I am not sure what you mean by using HTTPOpenRequest, sorry! I have been so use to using the nice n simple Indy components!
Oh and btw the code example I am using came from you I think in another thread, so it's all your fault! ;-)
Cheers,
Just.
Oh and btw the code example I am using came from you I think in another thread, so it's all your fault! ;-)
Cheers,
Just.
Well, seeing as the content you are trying to retrieve is dynamically generated, it is possible
that the server can not pass the content-length to you.
that the server can not pass the content-length to you.
ASKER
hmm, that's a thought, but surely the server would generate the file first before accepting commands like this otherwise you could access the magical google script? will play with it to see if initializing FileSize solves it, I did try other static urls too so probably right on this one. Trying now..
Just.
Just.
ASKER
Sorry to be stupid Eddie but I just can't get this working, how do I initialize FileSize? I tried using Initialize(FileSize,-1) and FileSize := -1 already.
I also need to get the content type now (text/html) etc maybe you would be kind enough to show me how to retrieve this while i'm getting the FileSize, i imagine this is just one or two more lines of code added?
Thanks for your help, and sorry again for being so stupid.
Just.
I also need to get the content type now (text/html) etc maybe you would be kind enough to show me how to retrieve this while i'm getting the FileSize, i imagine this is just one or two more lines of code added?
Thanks for your help, and sorry again for being so stupid.
Just.
ASKER
Also worth mentioning I think is that I am using Delphi 5 Pro, i think this has some bearing on the buffer side doesn't it? not that I know what i'm talking about..
SOLUTION
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
ASKER
Ok, cheers man. Appreciate your help.
ASKER CERTIFIED SOLUTION
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
ASKER
Thanks for clarrifying Russell, I didn't realise that, it is probably best if I avoid trying to retrieve the size at all then incase the server does not pass it sometimes. Seems only fair to split points, hope this is ok.
I am also wondering how easy it is to modify the code I am using to get Content-Type: text/html instead? or should this be a new question?
Thanks for your help,
JustinWillis.
I am also wondering how easy it is to modify the code I am using to get Content-Type: text/html instead? or should this be a new question?
Thanks for your help,
JustinWillis.
Getting COntent-Type:
var
hSession: HINTERNET;
hService: HINTERNET;
CType: String;
dwSize, Reserved: DWORD;
err: string;
begin
hSession := InternetOpen( 'MyApp', INTERNET_OPEN_TYPE_PRECONF IG, nil, nil, 0 );
if Assigned( hSession ) then
begin
hService := InternetOpenUrl(hSession, PChar('http://www.google.co.uk/search?hl=en&safe=off&q=test&meta='), nil, 0, 0, 0);
if Assigned( hService ) then
begin
SetLength(CType, 256);
dwSize := 256;
Reserved := 0;
if HttpQueryInfo(hService, HTTP_QUERY_CONTENT_TYPE,
@CType[1], dwSize , Reserved) then
begin
Memo1.Lines.Add( CType);
end
else
begin
err := SysErrorMessage(GetLastErr or);
Memo1.Lines.Add(err);
end;
end;
InternetCloseHandle( hService );
end;
InternetCloseHandle( hSession );
end;
var
hSession: HINTERNET;
hService: HINTERNET;
CType: String;
dwSize, Reserved: DWORD;
err: string;
begin
hSession := InternetOpen( 'MyApp', INTERNET_OPEN_TYPE_PRECONF
if Assigned( hSession ) then
begin
hService := InternetOpenUrl(hSession, PChar('http://www.google.co.uk/search?hl=en&safe=off&q=test&meta='), nil, 0, 0, 0);
if Assigned( hService ) then
begin
SetLength(CType, 256);
dwSize := 256;
Reserved := 0;
if HttpQueryInfo(hService, HTTP_QUERY_CONTENT_TYPE,
@CType[1], dwSize , Reserved) then
begin
Memo1.Lines.Add( CType);
end
else
begin
err := SysErrorMessage(GetLastErr
Memo1.Lines.Add(err);
end;
end;
InternetCloseHandle( hService );
end;
InternetCloseHandle( hSession );
end;
Being that you are already using wininet, and have gone though the steps of generating a request, it would make sense just to use HttpQueryInfo with the flag of HTTP_QUERY_CONTENT_TYPE.
eg:
var
lpBuffer: Array [0..1024] of Char;
dwSize:=Pred(SizeOf(lpBuff er));
if HttpQueryInfo(hService, HTTP_QUERY_CONTENT_TYPE, @lpBuffer, dwSize, Reserved) then
begin
// lpBuffer contains the content type
// ...
end;
-----------
Russell
eg:
var
lpBuffer: Array [0..1024] of Char;
dwSize:=Pred(SizeOf(lpBuff
if HttpQueryInfo(hService, HTTP_QUERY_CONTENT_TYPE, @lpBuffer, dwSize, Reserved) then
begin
// lpBuffer contains the content type
// ...
end;
-----------
Russell
ASKER
Cheers guys,
Will play with this using your examples but I am sure it will work fine.
Thanks again,
JustinWillis.
Will play with this using your examples but I am sure it will work fine.
Thanks again,
JustinWillis.
ASKER