Загрузка файла из интернета, HttpSendRequest не удается с кодом ошибки

0

Я создаю программу, которая может загружать файлы из Интернета. Прежде чем загрузить файл, я хочу получить размер файла, и я попробовал 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;
}
Теги:

1 ответ

3
Лучший ответ

При вызове 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(). Позвольте ему обрабатывать эти детали для вас.

  • 0
    Спасибо за ваш быстрый и отличный ответ. Для тех, кто использует HttpQueryInfo для получения размера файла, обязательно включите флаг HTTP_QUERY_FLAG_NUMBER.

Ещё вопросы

Сообщество Overcoder
Наверх
Меню