Thanks in advance
--
Olivier Gilloire,
ftiw1...@wanadoo.fr
Olivier Gilloire <ftiw1...@wanadoo.fr> wrote in article
<01bc5aeb$82112f70$3084fcc1@holyland>...
> (MFC4.2/VC5.0)
> How can I get a CInternetFile size ? I tried CFile::GetLength(), but it
> returns a wrong value. An idea ? I need to show the percentage of the
> transfer being done
I am assuming you are transferring the file from an HTTP server,
as the GetLength() method works for file:// or ftp:// URLs.
I have just had to solve this very issue. CInternetFile::GetLength()
calls InternetQueryDataAvailable which simply tells you the number
of bytes available in the next buffer, not the total length of the file.
I personally think this is very misleading given the semantics of
CFile::GetLength() (i.e. get total file length). I've reported this to
Microsoft, but of course received no response.
Instead what you need to do is to query the HTTP headers that
come back from the server - one of these (content length) has the
information you want. However in the process of trying to do this
I discovered some other MFC "bugs" or oversights in this area,
so the following code is quite ugly. If anyone knows a better way
of doing this, I would appreciate hearing it. Of course if you already
know that your session is HTTP (i.e. you have not used the generic
OpenURL with any old URL), then you will not have these problems.
// NOTE: the extra parameters on the OpenURL call are required
// in order to download executable files from an IIS server.
CStdioFile* file = session.OpenURL(fullURL, 1,
INTERNET_FLAG_TRANSFER_BINARY, "Accept: */*\r\n\r\n", -1);
// cope with NULL file pointer...
// Set up the progress dialog's length field. Note that for
// a CInternetFile (e.g. HTTP), the GetLength() method is
// completely useless - it returns the size of the next buffer
// rather than the total file. In this case we need to use
// HttpQueryInfo to get the content length.
// MFC BUG: MFC 5.0 does not export the runtime classes for
// CInternetFile and its derived classes - this seems to be
// a mistake. Therefore we need to use AfxParseURL
// to figure it out from the URL.
DWORD totalLen = 0;
DWORD serviceType = AFX_INET_SERVICE_UNK;
CString dummy1, dummy2;
INTERNET_PORT port;
VERIFY(AfxParseURL(fullURL, serviceType, dummy1, dummy2, port));
switch(serviceType)
{
case AFX_INET_SERVICE_FILE:
case AFX_INET_SERVICE_FTP:
totalLen = file->GetLength(); // for file:// or ftp://
break;
case AFX_INET_SERVICE_HTTP:
{
DWORD dwBufLen = sizeof(totalLen);
if (!((CHttpFile*)file)->QueryInfo(HTTP_QUERY_CONTENT_LENGTH |
HTTP_QUERY_FLAG_NUMBER,
&totalLen, &dwBufLen) || dwBufLen != sizeof(totalLen))
totalLen = 0;
break;
}
default:
totalLen = 0; // Gopher or other - don't know length
}
Hope this helps,
Ellis.
-----
Ellis Brover
E & L Consulting
mailto:ebr...@ozemail.com.au