如何在 C/C++ 中使用 WinHTTP 下载文件?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/822714/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-27 17:26:52  来源:igfitidea点击:

How to download a file with WinHTTP in C/C++?

c++cwindowshttpwinhttp

提问by

I know how to download an html/txt page. For example :

我知道如何下载 html/txt 页面。例如 :

//Variables 
DWORD dwSize = 0;
DWORD dwDownloaded = 0;
LPSTR pszOutBuffer;
vector <string>  vFileContent;
BOOL  bResults = FALSE;
HINTERNET  hSession = NULL, 
           hConnect = NULL,
           hRequest = NULL;

// Use WinHttpOpen to obtain a session handle.
hSession = WinHttpOpen( L"WinHTTP Example/1.0",  
                        WINHTTP_ACCESS_TYPE_DEFAULT_PROXY,
                        WINHTTP_NO_PROXY_NAME, 
                        WINHTTP_NO_PROXY_BYPASS, 0);

// Specify an HTTP server.
if (hSession)
    hConnect = WinHttpConnect( hSession, L"nytimes.com",
                               INTERNET_DEFAULT_HTTP_PORT, 0);

// Create an HTTP request handle.
if (hConnect)
    hRequest = WinHttpOpenRequest( hConnect, L"GET", L"/ref/multimedia/podcasts.html",
                                   NULL, WINHTTP_NO_REFERER, 
                                   NULL, 
                                   NULL);

// Send a request.
if (hRequest)
    bResults = WinHttpSendRequest( hRequest,
                                   WINHTTP_NO_ADDITIONAL_HEADERS,
                                   0, WINHTTP_NO_REQUEST_DATA, 0, 
                                   0, 0);


// End the request.
if (bResults)
    bResults = WinHttpReceiveResponse( hRequest, NULL);

// Keep checking for data until there is nothing left.
if (bResults)
    do 
    {

        // Check for available data.
        dwSize = 0;
        if (!WinHttpQueryDataAvailable( hRequest, &dwSize))
            printf( "Error %u in WinHttpQueryDataAvailable.\n",
                    GetLastError());

        // Allocate space for the buffer.
        pszOutBuffer = new char[dwSize+1];
        if (!pszOutBuffer)
        {
            printf("Out of memory\n");
            dwSize=0;
        }
        else
        {
            // Read the Data.
            ZeroMemory(pszOutBuffer, dwSize+1);

            if (!WinHttpReadData( hRequest, (LPVOID)pszOutBuffer, 
                                  dwSize, &dwDownloaded))
            {
                printf( "Error %u in WinHttpReadData.\n", 
                        GetLastError());
            }
            else
            {
                        printf("%s", pszOutBuffer);
                            // Data in vFileContent
                vFileContent.push_back(pszOutBuffer);
            }

            // Free the memory allocated to the buffer.
            delete [] pszOutBuffer;
        }

    } while (dwSize>0);


// Report any errors.
if (!bResults)
    printf("Error %d has occurred.\n",GetLastError());

// Close any open handles.
if (hRequest) WinHttpCloseHandle(hRequest);
if (hConnect) WinHttpCloseHandle(hConnect);
if (hSession) WinHttpCloseHandle(hSession);

// Write vFileContent to file
ofstream out("test.txt",ios::binary);
for (int i = 0; i < (int) vFileContent.size();i++)
out << vFileContent[i];
out.close();

When I try to download a picture, I get only the first lines of the file and no error message. The problem seems related to this parameter (ppwszAcceptTypes) in WinHttpOpenRequest Function.

当我尝试下载图片时,我只得到文件的第一行,没有错误消息。该问题似乎与 WinHttpOpenRequest 函数中的此参数 (ppwszAcceptTypes) 有关。

link text

链接文字

采纳答案by Lou Franco

回答by

Solution :

解决方案 :

FILE * pFile; // NEW
pFile = fopen("file.bin", "w+b"); // NEW

if (bResults)
    do 
    {
        // Check for available data.
        dwSize = 0;
        if (!WinHttpQueryDataAvailable( hRequest, &dwSize))
            printf( "Error %u in WinHttpQueryDataAvailable.\n",
                    GetLastError());

        // Allocate space for the buffer.
        pszOutBuffer = new char[dwSize+1];



        if (!pszOutBuffer)
        {
            printf("Out of memory\n");
            dwSize=0;
        }
        else
        {
            // Read the Data.
            ZeroMemory(pszOutBuffer, dwSize+1);

            if (!WinHttpReadData( hRequest, (LPVOID)pszOutBuffer, 
                                  dwSize, &dwDownloaded))
            {
                printf( "Error %u in WinHttpReadData.\n", 
                        GetLastError());
            }
            else
            {
                            printf("%s", pszOutBuffer);
                fwrite(pszOutBuffer, (size_t)dwDownloaded, (size_t)1, pFile); // NEW

            }

            // Free the memory allocated to the buffer.
            delete [] pszOutBuffer;
        }

    } while (dwSize>0);

fclose (pFile); // NEW

回答by

Merely opening the ofstream in binary mode does not change the way that the << operators work - they will always perfform formatted output. You need to use the stream's write() function, which does unformatted output.

仅以二进制模式打开 ofstream 不会改变 << 运算符的工作方式 - 它们将始终执行格式化输出。您需要使用流的 write() 函数,该函数执行未格式化的输出。