Thread View: borland.public.cppbuilder.internet.web
11 messages
11 total messages
Started by Boba
Tue, 02 Jan 2007 06:21
downloading with wininet
Author: Boba
Date: Tue, 02 Jan 2007 06:21
Date: Tue, 02 Jan 2007 06:21
44 lines
2489 bytes
2489 bytes
Happy New Year!
I'm trying to figure out what's wrong with the following code.
Please help. Thanks.
void DownloadFile( LPCSTR szServerName, LPCSTR szFileName ){
HINTERNET hHttpNet, hHttpSession, hHttpRequest;
DWORD dwDataSize, dwBytesDownloaded;
LPCSTR szAcceptTypes[] = { "*.*", NULL };
BYTE Buffer[1024];
hHttpNet = InternetOpen( "Microsoft Internet Explorer",
INTERNET_OPEN_TYPE_PRECONFIG,
NULL, NULL, 0 );
if( hHttpNet ){
hHttpSession = InternetConnect( hHttpNet, szServerName,
INTERNET_DEFAULT_HTTP_PORT,
"anonymous", "",
INTERNET_SERVICE_HTTP, 0, 0 );
if( hHttpSession ){
hHttpRequest = HttpOpenRequest( hHttpSession, "GET", szFileName,
"HTTP/1.1", NULL, szAcceptTypes,
INTERNET_FLAG_RELOAD, 0 );
if( hHttpRequest ){
if( HttpSendRequest( hHttpRequest, NULL, 0, NULL, 0 ) ){
do{
if( InternetQueryDataAvailable( hHttpRequest, &dwDataSize, 0, 0 ) ){
if( InternetReadFile( hHttpRequest, (LPVOID)Buffer,
sizeof(Buffer),
&dwBytesDownloaded ) ){
/*write the data*/
}//if( InternetReadFile
}//if( InternetQueryDataAvailable(
} while( dwBytesDownloaded );
}//if( HttpSendRequest
InternetCloseHandle( hHttpRequest );
}//if( hHttpRequest )
InternetCloseHandle( hHttpSession );
}//if( hHttpSession )
InternetCloseHandle( hHttpNet );
}//if( hHttpNet )
}//DownloadFile
Re: downloading with wininet
Author: Remy Lebeau (TeamB)
Date: Tue, 02 Jan 2007 09:27
Date: Tue, 02 Jan 2007 09:27
35 lines
2154 bytes
2154 bytes
"Boba" <Boba@somewhere.world> wrote in message
news:4599f9c5@newsgroups.borland.com...
> LPCSTR szAcceptTypes[] = { "*.*", NULL };
That is wrong. HttpOpenRequest() expects a media ContentType mask,
not a filename mask. At the verly least, you need to change *.*" to
"*/*", ie:
LPCSTR szAcceptTypes[] = { "*/*", NULL };
> hHttpRequest = HttpOpenRequest( hHttpSession, "GET",
szFileName,
> "HTTP/1.1", NULL,
szAcceptTypes,
> INTERNET_FLAG_RELOAD, 0 );
What exactly are you passing as the szFileName? It needs to be a URL
relative to the root of the server, not a local file path. Why are
you passing the server name separately from the filename in the first
place? You should use InternetCraskUrl() to convert a single full URL
string into the individual parts that InternetOpen(),
InternetConnect(), and HttpOpenRequest() are all expecting.
> do{
> if( InternetQueryDataAvailable( hHttpRequest,
&dwDataSize, 0, 0 ) ){
I suggest you use HttpQueryInfo() to retreive the size of the data
before then entering the loop. That way you know when to stop looping
properly.
Gambit
Re: downloading with wininet
Author: Boba
Date: Tue, 02 Jan 2007 16:36
Date: Tue, 02 Jan 2007 16:36
40 lines
2264 bytes
2264 bytes
"Remy Lebeau (TeamB)" <no.spam@no.spam.com> wrote in message
news:459a2c13$1@newsgroups.borland.com...
> ...
> > LPCSTR szAcceptTypes[] = { "*.*", NULL };
>
> That is wrong. HttpOpenRequest() expects a media ContentType mask,
> not a filename mask. At the verly least, you need to change *.*" to
> "*/*", ie:
...hmmm... both gave the same result. i wish i knew why.
> LPCSTR szAcceptTypes[] = { "*/*", NULL };
>
> > hHttpRequest = HttpOpenRequest( hHttpSession, "GET",
> szFileName,
> > "HTTP/1.1", NULL,
> szAcceptTypes,
> > INTERNET_FLAG_RELOAD, 0 );
>
> What exactly are you passing as the szFileName? It needs to be a URL
> relative to the root of the server, not a local file path.
here's a sample call: DownloadFile("download.microsoft.com",
"/download/6/a/f/6af940c1-2774-4ebb-8546-2c83068af231/Windows2000-KB926247-x86-E
NU.EXE");
> Why are you passing the server name separately from the filename in the first
> place?
that's the way 'they' want.
> I suggest you use HttpQueryInfo() to retreive the size of the data
> before then entering the loop.
InternetQueryDataAvailable() is supposed to do that.
> That way you know when to stop looping properly.
if no (more) data avalable, dwBytesDownloaded will be set 0
by the InternetReadFile() call.
Re: downloading with wininet
Author: Remy Lebeau (TeamB)
Date: Tue, 02 Jan 2007 18:44
Date: Tue, 02 Jan 2007 18:44
95 lines
4041 bytes
4041 bytes
"Boba" <Boba@somewhere.world> wrote in message
news:459a89d6@newsgroups.borland.com...
> ...hmmm... both gave the same result. i wish i knew why.
Considering that none of your code is doing any error handling, you
did not specify the contents of the values you are passing, and you
did not specify on which line the failure is actually occuring, there
is no way to diagnose your problem. You need to provide more
information.
> here's a sample call: DownloadFile("download.microsoft.com",
>
"/download/6/a/f/6af940c1-2774-4ebb-8546-2c83068af231/Windows2000-KB92
6247-x86-E
> NU.EXE");
Ok so far. Though again, there is no reason to separate the server
from the path like that. You should be passing it as a single
complete URL string, ie:
DownloadFile("http://download.microsoft.com/download/6/a/f/6af940c1-27
74-4ebb-8546-2c83068af231/Windows2000-KB926247-x86-ENU.EXE");
> > I suggest you use HttpQueryInfo() to retreive the size of the data
> > before then entering the loop.
>
> InternetQueryDataAvailable() is supposed to do that.
Your looping code is wrong anyway. You are not using the value that
InternetQueryDataAvailable() returns. You must read everything that
InternetQueryDataAvailable() reports, or else it cannot report more
data later. This is clearly stated in the documentation. You need to
change your loop to something more like the following instead:
BYTE Buffer[1024];
DWORD dwDataSize, dwBytesToRead, dwBytesRead, dwBytesDownloaded;
dwBytesDownloaded = 0;
while( InternetQueryDataAvailable(hHttpRequest, &dwDataSize, 0,
0) )
{
if( dwDataSize == 0 )
break;
do
{
dwNumToRead = min(dwDataSize, sizeof(Buffer));
if( !InternetReadFile(hHttpRequest, Buffer, dwBytesToRead,
&dwBytesRead) )
break;
// write the data...
dwDataSize -= dwBytesRead;
dwBytesDownloaded += dwBytesRead;
}
while( dwDataSize != 0 );
}
However, I strongly suggest you use HttpQueryInfo() instead of
InternetQueryDataAvailable(). Then you need only 1 loop instead of 2,
since the download already knows the full size of the data ahead of
time, ie:
BYTE Buffer[1024];
DWORD dwDataSize, dwBytesToRead, dwBytesRead, dwBytesDownloaded,
dwIndex = 0;
DWORD dwLen = sizeof(dwDataSize);
dwBytesDownloaded = 0;
if( HttpQueryInfo(hHttpRequest, HTTP_QUERY_CONTENT_LENGTH |
HTTP_QUERY_FLAG_NUMBER, &dwDataSize, &dwLen, &dwIndex) )
{
while( dwDataSize != 0 )
{
dwNumToRead = min(dwDataSize, sizeof(Buffer));
if( !InternetReadFile(hHttpRequest, Buffer, dwBytesToRead,
&dwBytesRead) )
break;
// write the data...
dwDataSize -= dwBytesRead;
dwBytesDownloaded += dwBytesRead;
}
}
Gambit
Re: downloading with wininet
Author: Boba
Date: Tue, 02 Jan 2007 19:29
Date: Tue, 02 Jan 2007 19:29
28 lines
2211 bytes
2211 bytes
"Remy Lebeau (TeamB)" <no.spam@no.spam.com> wrote in message news:459aac49$1@newsgroups.borland.com... > ... > Considering that none of your code is doing any error handling, you > did not specify the contents of the values you are passing, and you > did not specify on which line the failure is actually occuring, there > is no way to diagnose your problem. You need to provide more > information. the error checking has been stripped off to simplify the post. there is no code line where it fails: it is the result of downloading that is sometimes wrong. at random, the file i get is the 406 error message (none of the code lines report a failure). some servers never send 406; others - like the one in my sample - do it at no obvious reason for that. let say i call the function 5 times in a raw on the same file and 2 times i may get a 406.html file instead. > Your looping code is wrong anyway. You are not using the value that > InternetQueryDataAvailable() returns. You must read everything that > InternetQueryDataAvailable() reports, or else it cannot report more > data later. i do read everything (not shown for the sake of simplicity). > However, I strongly suggest you use HttpQueryInfo() instead of > InternetQueryDataAvailable(). i will try it shortly.
Re: downloading with wininet
Author: Remy Lebeau (TeamB)
Date: Tue, 02 Jan 2007 20:30
Date: Tue, 02 Jan 2007 20:30
70 lines
3790 bytes
3790 bytes
"Boba" <Boba@somewhere.world> wrote in message
news:459ab27c@newsgroups.borland.com...
> the error checking has been stripped off to simplify the post.
> there is no code line where it fails: it is the result of
downloading
> that is sometimes wrong. at random, the file i get is the 406 error
> message (none of the code lines report a failure).
Well, you are not checking the actual response code to begin with
before downloading the file. 406 is a "not acceptable" error. You
have to use HttpQueryInfo() to verify the server's reply before you
can decide whether the file is ok to download or not.
> some servers never send 406; others - like the one in my
> sample - do it at no obvious reason for that.
I am assuming that you have not read RFC 2616 yet:
Hypertext Transfer Protocol -- HTTP/1.1
http://www.ietf.org/rfc/rfc2616.txt
10.4.7 406 Not Acceptable
The resource identified by the request is only capable of
generating
response entities which have content characteristics not
acceptable
according to the accept headers sent in the request.
Unless it was a HEAD request, the response SHOULD include an
entity
containing a list of available entity characteristics and
location(s)
from which the user or user agent can choose the one most
appropriate. The entity format is specified by the media type
given
in the Content-Type header field. Depending upon the format
and the
capabilities of the user agent, selection of the most
appropriate
choice MAY be performed automatically. However, this
specification
does not define any standard for such automatic selection.
Note: HTTP/1.1 servers are allowed to return responses which
are
not acceptable according to the accept headers sent in the
request. In some cases, this may even be preferable to sending
a
406 response. User agents are encouraged to inspect the
headers of
an incoming response to determine if it is acceptable.
If the response could be unacceptable, a user agent SHOULD
temporarily stop receipt of more data and query the user for a
decision on further actions.
> i do read everything (not shown for the sake of simplicity).
You are calling InternetReadFile() once, and only once, for each call
to InternetQueryDataAvailable(). If the size of the available data is
larger than your buffer, or InterntReadFile() cannot return that much
data in a single call, then you are NOT reading all of the available
data properly. That is why you must loop the call to
InterntReadFile() to ensure all available data is read in full.
Gambit
Re: downloading with wininet
Author: Remy Lebeau (TeamB)
Date: Tue, 02 Jan 2007 20:36
Date: Tue, 02 Jan 2007 20:36
12 lines
1313 bytes
1313 bytes
"Boba" <Boba@somewhere.world> wrote in message news:459ac5e4@newsgroups.borland.com... > i'm getting exactly the same behavior: once in a while the file > downloaded is just a 406.html message. That is because your requests are wrong to begin with, and you are not checking the server's response code. Please see my other reply. Gambit
Re: downloading with wininet
Author: Boba
Date: Tue, 02 Jan 2007 20:52
Date: Tue, 02 Jan 2007 20:52
10 lines
1368 bytes
1368 bytes
"Remy Lebeau (TeamB)" <no.spam@no.spam.com> wrote in message news:459aac49$1@newsgroups.borland.com... > ... > However, I strongly suggest you use HttpQueryInfo() instead of > InternetQueryDataAvailable(). i'm getting exactly the same behavior: once in a while the file downloaded is just a 406.html message. so, how do i tell the server that my client is aware of all these MIME settings and that it does accept the MIME type of the requested page.
Re: downloading with wininet
Author: Boba
Date: Tue, 02 Jan 2007 21:13
Date: Tue, 02 Jan 2007 21:13
22 lines
2149 bytes
2149 bytes
"Remy Lebeau (TeamB)" <no.spam@no.spam.com> wrote in message news:459ac541$1@newsgroups.borland.com... > ... > I am assuming that you have not read RFC 2616 yet: you've got that right. > You are calling InternetReadFile() once, and only once, for each call > to InternetQueryDataAvailable(). If the size of the available data is > larger than your buffer, or InterntReadFile() cannot return that much > data in a single call, then you are NOT reading all of the available > data properly. That is why you must loop the call to > InterntReadFile() to ensure all available data is read in full. i do loop InternetReadFile untill dwBytesDownloaded becomes 0. my problem is not in reading the file, but in convincing the server in client's ability to accept that type of file. the server responds with 406 in a very strange inconsistency, which means i've got to tell it first that i am aware of teh potential MIME problems. i don't understand why the server is not pursistant in its response and how do i create my request header properly.
Re: downloading with wininet
Author: Remy Lebeau (TeamB)
Date: Wed, 03 Jan 2007 01:06
Date: Wed, 03 Jan 2007 01:06
56 lines
3254 bytes
3254 bytes
"Boba" <Boba@somewhere.world> wrote in message
news:459acad3@newsgroups.borland.com...
> i do loop InternetReadFile untill dwBytesDownloaded becomes 0.
No, you are not. I quote your original code:
do{
if( InternetQueryDataAvailable( hHttpRequest, &dwDataSize, 0,
0 ) ){
if( InternetReadFile( hHttpRequest, (LPVOID)Buffer,
sizeof(Buffer), &dwBytesDownloaded ) ){
/*write the data*/
}//if( InternetReadFile
}//if( InternetQueryDataAvailable(
} while( dwBytesDownloaded );
You are looping InternetQueryDataAvailable(), not InternetReadFile().
Again, if you do not read ALL of the data that
InternetQueryDataAvailable() reports in a single call, it CANNOT
report more data until the previous data queue is emptied. This is
clearly stated by Microsoft's documentation:
InternetQueryDataAvailable
http://msdn2.microsoft.com/en-us/library/aa385100.aspx
"This function returns the number of bytes of data that are
available to be read immediately by a subsequent call to
InternetReadFile. If there is currently no data available and the end
of the file has not been reached, the request waits until data becomes
available. The amount of data remaining will not be recalculated until
all available data indicated by the call to InternetQueryDataAvailable
is read."
Read the last sentence very carefully. After you call
InternetQueryDataAvailable(), you must read ALL available data before
you can call InternetQueryDataAvailable() again.
> my problem is not in reading the file
It may not be the original problem you were asking about, but it is
another problem in your code nontheless that you must address
properly.
> but in convincing the server in client's ability to accept that type
of file.
Had you read the RFC that I pointed you to, you would see that when a
406 reply is returned by the server, the reply data includes
alternative characteristics and locations that you must use to
download the content, as the original criteria you provided will not
work for what you are trying to download.
Gambit
Re: downloading with wininet
Author: Boba
Date: Wed, 03 Jan 2007 02:35
Date: Wed, 03 Jan 2007 02:35
4 lines
1274 bytes
1274 bytes
Thank you very much, Gambit. The information you have provided during this conversation was very helpful in resolving the problem with my code. Boba
Thread Navigation
This is a paginated view of messages in the thread with full content displayed inline.
Messages are displayed in chronological order, with the original post highlighted in green.
Use pagination controls to navigate through all messages in large threads.
Back to All Threads