2009-05-05 23 views
10

Wiem, jak pobrać stronę html/txt. Na przykład:Jak pobrać plik z WinHTTP w 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(); 

Gdy próbuję pobrać zdjęcie, otrzymuję tylko pierwsze wiersze pliku i brak komunikatu o błędzie. Problem wydaje się związany z tym parametrem (ppwszAcceptTypes) w funkcji WinHttpOpenRequest.

link text

+0

Wystarczy mała uwaga na temat dynamicznej alokacji pamięci - należy ją przydzielić jak 'pszOutBuffer = new char [dwSize + 1] ;, a następnie sprawdzić wskaźnik. Nie powinieneś, ponieważ nowy operator rzuci wyjątek w przypadku braku pamięci domyślnie. Aby temu zapobiec, powinieneś dostarczyć 'std :: nothrow' nowemu operatorowi, takiemu jak' pszOutBuffer = new (std :: nothrow) char [dwSize + 1]; - w takim przypadku wskaźnik będzie miał wartość null, jeśli jest brak pamięciowy. –

+0

Zaimportuj bibliotekę msxml6. Jest dostarczany z (Vista może? Win7 na pewno i na górę) i jest instalowalny na XP. Zainicjuj COM i utwórz obiekt IXMLHTTPRequest i wyślij żądanie. Znacznie łatwiejsze niż biblioteki WinHttp i certyfikaty żonglowania. https://msdn.microsoft.com/en-us/library/ms759148(v=vs.85).aspx – jmucchiello

Odpowiedz

6

Rozwiązanie:

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

Samo otwarcie ofstream w trybie binarnym nie zmienia sposób działania operatorów < < - zawsze będą działać perfekcyjnie sformatowane wyjście. Musisz użyć funkcji write() strumienia, która wykonuje niesformatowane dane wyjściowe.