I'm a new guy on the website here, so forgive me if I do anything wrong in this post.
I'm working with WinINet
and trying to download a binary file
from the internet but, for some reason when I get to the point of actually downloading that file using InternetReadFile()
, it returns reading nothing at all (0 bytes of information read). Running the Visual Studio 2012 debugger
revealed that detail to me, because the HINTERNET
handler that I feed into the API call definitely has data for sure. I just don't understand what I'm doing wrong. Maybe you guys can help?
The basic gist of my program is that I'm downloading a binary file from the net, and saving it into a temporary file that's in a temporary directory. After copying the contents into the temporary file, I transfer that temp file's binary data contents into another local file (this time within a valid directory). Here's what I have so far. Hopefully with the logic breakdown I provide, you guys will be able to follow it despite the length of code...
#include "httpfileretrieval.h" // contains all handlers (hInstance, etc.)
bool downloadFile(const char* lpszServer, const char* lpszUrl, const char* destPath)
{
FILE *tempFile = NULL;
FILE *localFile = NULL;
const int bufsize = 4096;
DWORD tempDirBytes;
DWORD dwSize = 4096; // experiment - ignore the fact this is the same as bufsize
DWORD dwRead = 0;
char lpszDataBuffer[bufsize];
lpszDataBuffer[bufsize] = '\0';
char tempPath[MAX_PATH];
char tempFileName[bufsize]; // will hold the FULL temp file path
std::string srcPath;
srcPath.append(lpszServer);
srcPath.append(lpszUrl); // http://www.domain.com/url into srcPath
hInstance = InternetOpen("httpfret",
INTERNET_OPEN_TYPE_PRECONFIG,
NULL,
NULL,
INTERNET_FLAG_ASYNC); // ASYNC Flag
if (!hInstance)
{
DWORD errorNum = GetLastError();
fprintf(stderr, "InternetOpen Failed! Windows Error %d\n", errorNum);
return false;
}
// Setup callback function due to INTERNET_FLAG_ASYNC
if (InternetSetStatusCallback(hInstance,(INTERNET_STATUS_CALLBACK)&Callback)
== INTERNET_INVALID_STATUS_CALLBACK)
{
DWORD errorNum = GetLastError();
fprintf(stderr, "InternetSetStatusCallback Failed! Windows Error %d\n", errorNum);
return false;
}
// First call that will actually complete asynchronously even though
// there is no network traffic
hConnect = InternetConnect(hInstance,
lpszServer,
INTERNET_DEFAULT_HTTP_PORT,
NULL,
NULL,hg
INTERNET_SERVICE_HTTP,
0,
1); // Connection handle's Context
if (!hConnect)
{
if (GetLastError() != ERROR_IO_PENDING)
{
DWORD errorNum = GetLastError();
fprintf(stderr, "InternetConnect Failed! Windows Error %d\n", errorNum);
InternetCloseHandle(hInstance);
return false;
}
// Wait until we get the connection handle
WaitForSingleObject(hConnectedEvent, INFINITE);
}
// Open the request
hRequest = HttpOpenRequest(hConnect, "GET", lpszUrl, NULL, NULL, NULL,
INTERNET_FLAG_RELOAD | INTERNET_FLAG_NO_CACHE_WRITE,
2); // Request handle's context
if (!hRequest)
{
if (GetLastError() != ERROR_IO_PENDING)
{
DWORD errorNum = GetLastError();
fprintf(stderr, "HttpOpenRequest Failed! Windows Error %d\n", errorNum);
InternetCloseHandle(hConnect);
InternetCloseHandle(hInstance);h
return false;
}
// Wait until we get the request handle
WaitForSingleObject(hRequestOpenedEvent, INFINITE);
}
// Send the request
if (!HttpSendRequest(hRequest, NULL, 0, NULL, 0))
{
if (GetLastError() != ERROR_IO_PENDING)
{
DWORD errorNum = GetLastError();
fprintf(stderr, "HttpSendRequest Failed! Windows Error %d\n", errorNum);
InternetCloseHandle(hRequest);
InternetCloseHandle(hConnect);
InternetCloseHandle(hInstance);
return false;
}
}
if (bVerbose)
{
printf("HttpSendRequest called successfully\n");
}
WaitForSingleObject(hRequestCompleteEvent, INFINITE);
// Before downloading file...
// 1. Get the temp directory
if (!(tempDirBytes = GetTempPathA(MAX_PATH, tempPath)))
{
fprintf(stderr, "Could not get temporary directory\n");
InternetCloseHandle(hRequest);
InternetCloseHandle(hConnect);
InternetCloseHandle(hInstance);
return false;
}
// 2. Get temp file name (full name: tempPath\temp.tmp)
srand(GetTickCount());
sprintf(tempFileName, "%s\\%08X.tmp", tempPath, rand());
// Error check the end of temp file name for ending double slash
if (tempFileName[bufsize] == '\\')
tempFileName[bufsize] = '\0';
// 3. Create temp file
printf("Creating temp file %s\nto store %s\n", tempFileName, srcPath.c_str());
tempFile = fopen(tempFileName, "wb"); // Open the file for writing
if (!tempFile)
{
DWORD errorNum = GetLastError();
fprintf(stderr, "Could not create temp file! Error %d\n", errorNum);
InternetCloseHandle(hRequest);
InternetCloseHandle(hConnect);
InternetCloseHandle(hInstance);
return false;
}
printf("Done!\n\n");
printf("------------------- Read the response -------------------\n");
unsigned long n = 0;
unsigned long sum = 0;
printf("Copying %s\n to %s\n", srcPath.c_str(), tempFileName);
// WHERE THE MAGIC HAPPENS - AND WHERE EVERYTHING FAILS!
while ( InternetReadFile(hRequest, lpszDataBuffer, dwSize, &dwRead) && !(bAllDone) )
{
if (dwRead != 0)
{
sum = 0;
fwrite(lpszDataBuffer, 1, dwRead, tempFile);
for (unsigned long i = 0; i < dwRead; ++i)
{
sum += lpszDataBuffer[i];
sum %= 0xFFFF;
}
printf("Received 4KB block %d. Sum %04X\r", n++, sum);
}
else
{
bAllDone = TRUE;
printf("\n");
break;
}
}
printf("\n\n------------------- Request Complete ----------------\n");
fclose(tempFile); // Done writing to file
tempFile = fopen(tempFileName, "rb"); // Reopen for reading
//Create the local file
printf("Creating local file %s\n", destPath);
localFile = fopen(destPath, "wb");
if (!localFile)
{
DWORD errorNum = GetLastError();
fprintf(stderr, "Could not create local file! Windows Error %d\n", errorNum);
fclose(tempFile);
remove(tempFileName); // delete temporary file from machine
InternetCloseHandle(hRequest);
InternetCloseHandle(hConnect);
InternetCloseHandle(hInstance);
return false;
}
printf("Done!\n\n");
// Copy the contents from the temp file to the local file
printf("Copying temp file %s contents\nto local file %s\n", tempFileName, destPath);
if (!copyFile(tempFile, localFile))
{
DWORD errorNum = GetLastError();
fprintf(stderr, "Could not copy temp file to local directory! Windows Error\n", errorNum);
fclose(tempFile);
remove(tempFileName); // delete temporary file from machine
fclose(localFile);
InternetCloseHandle(hRequest);
InternetCloseHandle(hConnect);
InternetCloseHandle(hInstance);
return false;
}
printf("Done!\n\n");
// end of logic housekeeping
fclose(tempFile);
printf("Deleting temp file %s\n", tempFileName);
remove(tempFileName); // delete temporary file from machine
printf("Done!\n\n");
fclose(localFile);
printf("Ending Internet Session\n");
InternetCloseHandle(hRequest);
InternetCloseHandle(hConnect);
InternetCloseHandle(hInstance);
printf("Done!\n");
printf("Press Enter to continue\n");
std::cin.get();
return true;
}