2009-05-05 24 views
10

So come scaricare una pagina html/txt. Per esempio:Come scaricare un file con WinHTTP in C/C++?

//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(); 

Quando si tenta di scaricare un'immagine, ottengo solo le prime righe del file e nessun messaggio di errore. Il problema sembra correlato a questo parametro (ppwszAcceptTypes) nella funzione WinHttpOpenRequest.

link text

+0

Solo una piccola annotazione sull'assegnazione dinamica della memoria - la si assegna come "pszOutBuffer = new char [dwSize + 1];" e dopo controlla il puntatore. Non si dovrebbe, perché il nuovo operatore genererà un'eccezione nel caso di mancanza di memoria di default. Per impedirlo dovresti fornire 'std :: nothrow' al nuovo operatore come questo' pszOutBuffer = new (std :: nothrow) char [dwSize + 1]; '- in tal caso il puntatore sarà nullo se c'è una mancanza di memoria. –

+0

Importare la libreria msxml6. Viene fornito con (vista forse? Win7 di sicuro e su) ed è installibile su XP. Avvia COM e crea un oggetto IXMLHTTPRequest e invia una richiesta. Molto più facile delle librerie WinHttp e dei cerini di giocoleria. https://msdn.microsoft.com/en-us/library/ms759148(v=vs.85).aspx – jmucchiello

risposta

6

Soluzione:

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 
5

Semplicemente aprendo l'ofstream in modalità binaria Non cambia il modo in cui funzionano gli operatori < - perverranno sempre output formattato. È necessario utilizzare la funzione write() del flusso, che esegue l'output non formattato.

Problemi correlati