Я создаю программу, которая может загружать файлы из Интернета. Прежде чем загрузить файл, я хочу получить размер файла, и я попробовал InternetQueryDataAvailable, но он дает значение 0.
Затем я попробовал hHttpRequest, но он дает код ошибки ERROR_HTTP_HEADER_NOT_FOUND. Поэтому я добавил HttpSendRequest, но его код ошибки ERROR_INTERNET_INVALID_URL.
Я использую сайт avg как тестовый сайт: http://free.avg.com/us-en/download-free-all-product
Файл для загрузки: avg_free_x86_all_2014_4259a6848.exe
Любая помощь будет приятной, спасибо.
Код:
DWORD DownloadFile(PCHAR SaveDirectory)
{
HINTERNET hInternet;
CHAR StrBuffer[100];
hInternet = InternetOpen(InternetAgent, PRE_CONFIG_INTERNET_ACCESS, NULL, INTERNET_INVALID_PORT_NUMBER, 0);
if (hInternet != NULL)
{
CHAR TestUrl[] = "http://download.avgfree.com/filedir/inst";
CHAR TestFileName[] = "avg_free_x86_all_2014_4259a6848.exe";
HINTERNET hHttpSession = InternetConnect(hInternet, TestUrl, INTERNET_DEFAULT_HTTP_PORT, NULL, NULL, INTERNET_SERVICE_HTTP, 0, 0);
if (hHttpSession != NULL)
{
PCTSTR AcceptTypes[] = {"text/*", "application/exe", "application/zlib", "application/gzip", "application/applefile", NULL};
//I dont think application/exe is valid, but i could Not find a .exe format in the msdn list.
//http://www.iana.org/assignments/media-types/media-types.xhtml#application for the list
HINTERNET hHttpRequest = HttpOpenRequest(hHttpSession, "GET", TestFileName, "HTTP/1.1", TestUrl, &AcceptTypes[0],
INTERNET_FLAG_EXISTING_CONNECT|INTERNET_FLAG_RELOAD|INTERNET_FLAG_DONT_CACHE, 0);
if (hHttpRequest != NULL)
{
DWORD FileSize = 0;
DWORD BufferLength = sizeof(FileSize);
if (HttpSendRequest(hHttpRequest, NULL, 0, NULL, 0))
{
//See if HttpQueryInfo can get the file size.
if (HttpQueryInfo(hHttpRequest, HTTP_QUERY_CONTENT_LENGTH, &FileSize, &BufferLength, NULL))
{
sprintf_s(StrBuffer, sizeof(StrBuffer), "%u", FileSize);
MessageBox(MainWinHwnd, StrBuffer, "File Size", MB_OK);
}
else MessageBox(MainWinHwnd, "Failed to get the file size.", NULL, MB_OK);
//See if InternetQueryDataAvailable can get the file size.
if (InternetQueryDataAvailable(hHttpRequest, &FileSize, 0, 0))
{
sprintf_s(StrBuffer, sizeof(StrBuffer), "%u", FileSize);
MessageBox(MainWinHwnd, StrBuffer, "File Size", MB_OK);
}
else
{
MessageBox(MainWinHwnd, "Failed to get the file size.", NULL, MB_OK);
}
}
else
{
DWORD LastError = GetLastError();
sprintf_s(StrBuffer, sizeof(StrBuffer), "%u", LastError);
MessageBox(NULL, StrBuffer, NULL, MB_OK);
}
InternetCloseHandle(hHttpRequest);
}
else MessageBox(NULL, "Error #3", NULL, MB_OK);
InternetCloseHandle(hHttpSession);
}
else MessageBox(NULL, "Error #2", NULL, MB_OK);
InternetCloseHandle(hInternet);
}
else MessageBox(NULL, "Error #1", NULL, MB_OK);
return TRUE;
}
При вызове InternetConnect()
укажите только "download.avgfree.com"
самостоятельно для имени хоста, а не URL-адреса.
При вызове HttpOpenRequest()
укажите "/filedir/inst/avg_free_x86_all_2014_4259a6848.exe"
как объект для запроса, а не имя файла.
Используйте InternetCrackUrl()
, чтобы разделить полный URL на отдельные компоненты, передавая lpszHostName
и nPort
полей в InternetConnect()
и lpszUrlPath
поле для HttpOpenRequest()
.
Вам также не нужно знать размер файла для загрузки. Фактически, когда загрузка начинается, размер файла неизвестен. Иногда будет. В любом случае вы можете просто вызвать InternetReadFile()
в цикле, пока он не сообщит, что данных больше нет. Пусть он обрабатывает размер файла внутри вас.
BTW, посмотрите на URLDownloadToFile()
. Позвольте ему обрабатывать эти детали для вас.