Я новичок на сайте, так что простите, если я что-то не так делаю в этом посте.
Я работаю с WinINet
и пытается скачать binary file
из интернета, но по какой-то причине, когда я дохожу до момента фактической загрузки этого файла с помощью InternetReadFile()
, он вообще ничего не читает (прочитано 0 байт информации). Запуск Visual Studio 2012 debugger
раскрыл эту деталь мне, потому что HINTERNET
обработчик, который я передаю в вызов API, определенно содержит данные. Я просто не понимаю, что я делаю не так. Может быть, вы, ребята, можете помочь?
Основная суть моей программы заключается в том, что я загружаю двоичный файл из сети и сохраняю его во временный файл, который находится во временном каталоге. После копирования содержимого во временный файл я передаю содержимое двоичных данных этого временного файла в другой локальный файл (на этот раз в допустимом каталоге). Вот что у меня так далеко. Надеюсь, что с предоставленной мне логикой вы, ребята, сможете следовать ей, несмотря на длину кода …
#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;
}
Ваш код работает для меня. Вы уверены, что сервер возвращает непустой ответ? Вы можете использовать такой инструмент, как Fiddler2, чтобы проверить. В этом коде немало проблем, включая переполнение буфера: lpszDataBuffer[bufsize] = '\0';
, Кроме того, вы используете асинхронный режим, но у вас нет асинхронной обработки в цикле чтения. Я рекомендую вам выложить код для проверки здесь: https://codereview.stackexchange.com/.
Последнее замечание Если вы все равно будете ждать завершения каждой операции, то нет смысла делать что-то асинхронно. Вы можете оставить INTERNET_FLAG_ASYNC
флаг. Это сделает вашу функцию намного проще.
Других решений пока нет …