11

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

//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.

link text

  • Just a little remark on your dynamic memory allocation - you allocate it like `pszOutBuffer = new char[dwSize+1];` and after that check the pointer. You shouldn't, because the new operator will throw an exception in the case of memory lack by default. To prevent it you should supply `std::nothrow` to the new operator like this `pszOutBuffer = new(std::nothrow) char[dwSize+1];` - in that case the pointer will be null if there is a lack of memory. – Roman Kruglov Jun 04 '13 at 08:56
  • Import the msxml6 library. It ships with (vista maybe? win7 for sure and up) and is installible on XP. Initiate COM and the create an IXMLHTTPRequest object and send a request. Much easier than WinHttp libraries and juggling certs. https://msdn.microsoft.com/en-us/library/ms759148(v=vs.85).aspx – jmucchiello Dec 09 '16 at 00:44

3 Answers3

7

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.

6

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
2

Looks like this thread on MSDN is the same and has the solution

http://social.msdn.microsoft.com/forums/en-US/vclanguage/thread/45ccd91c-6794-4f9b-8f4f-865c76cc146d

Lou Franco
  • 87,846
  • 14
  • 132
  • 192
  • I've read this thread before, but the solution (opening the file in binary mode) didn't work for me. But I've just retried it, this time using C, not C++, and it works. So ofstream is not working with WinHttp, as far as I can tell. –  May 05 '09 at 01:36