Link to home
Start Free TrialLog in
Avatar of JustinWillis
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_PRECONFIG, 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.
Avatar of JustinWillis
JustinWillis

ASKER

Points Increased.
And Again!
Avatar of Eddie Shipman
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(GetLastError);
  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.
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.
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.
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.
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.
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.
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
Avatar of Eddie Shipman
Eddie Shipman
Flag of United States of America image

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
Ok, cheers man.  Appreciate your help.
ASKER CERTIFIED SOLUTION
Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
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.
Getting COntent-Type:

var
  hSession: HINTERNET;
  hService: HINTERNET;
  CType: String;
  dwSize, Reserved: DWORD;
  err: string;
begin
  hSession := InternetOpen( 'MyApp', INTERNET_OPEN_TYPE_PRECONFIG, 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(GetLastError);
        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(lpBuffer));
  if HttpQueryInfo(hService,  HTTP_QUERY_CONTENT_TYPE, @lpBuffer, dwSize, Reserved) then
  begin
     // lpBuffer contains the content type
     // ...
  end;

-----------

Russell


Cheers guys,

Will play with this using your examples but I am sure it will work fine.

Thanks again,
JustinWillis.