2013-01-21 24 views
1

我是這裏的網站上的新人,所以如果我在這篇文章中做了任何錯誤,請原諒我。InternetReadFile()似乎沒有讀取互聯網數據

我與WinINet工作,並試圖從網上下載一個binary file,但是,出於某種原因,當我到達的實際下載使用InternetReadFile()該文件中的點,則返回讀什麼都沒有(0字節的信息,請閱讀)。運行Visual Studio 2012 debugger向我透露了詳細信息,因爲我提供給API調用的HINTERNET處理程序肯定有數據。我只是不明白我做錯了什麼。也許你們可以幫忙?

我的程序的基本要點是我從網上下載一個二進制文件,並將其保存到臨時目錄中的臨時文件中。將內容複製到臨時文件後,我將該臨時文件的二進制數據內容轉移到另一個本地文件中(這次是在一個有效的目錄中)。這是迄今爲止我所擁有的。希望與邏輯故障我提供,你們將能夠按照它儘管代碼長度...

#include "httpfileretrieval.h" // contains all handlers (hInstance, etc.) 

bool downloadFile(const char* lpszServer, const char* lpszUrl, const char* destPath) 
{ 
    FILE *tempFile = NULL; 
    FILE *localFile = NULL; 

    const int bufsize = 4096; 
    DWORD tempDirBytes; 
    DWORD dwSize = 4096;   // experiment - ignore the fact this is the same as bufsize 
    DWORD dwRead = 0; 

    char lpszDataBuffer[bufsize]; 
    lpszDataBuffer[bufsize] = '\0'; 

    char tempPath[MAX_PATH]; 
    char tempFileName[bufsize]; // will hold the FULL temp file path 

    std::string srcPath; 
    srcPath.append(lpszServer); 
    srcPath.append(lpszUrl); // http://www.domain.com/url into srcPath 

    hInstance = InternetOpen("httpfret", 
         INTERNET_OPEN_TYPE_PRECONFIG, 
         NULL, 
         NULL, 
         INTERNET_FLAG_ASYNC); // ASYNC Flag 

    if (!hInstance) 
    { 
     DWORD errorNum = GetLastError(); 
     fprintf(stderr, "InternetOpen Failed! Windows Error %d\n", errorNum); 
     return false; 
    } 

    // Setup callback function due to INTERNET_FLAG_ASYNC 
    if (InternetSetStatusCallback(hInstance,(INTERNET_STATUS_CALLBACK)&Callback) 
    == INTERNET_INVALID_STATUS_CALLBACK) 
    { 
     DWORD errorNum = GetLastError(); 
     fprintf(stderr, "InternetSetStatusCallback Failed! Windows Error %d\n", errorNum); 
     return false; 
    } 

    // First call that will actually complete asynchronously even though 
    // there is no network traffic 
    hConnect = InternetConnect(hInstance, 
          lpszServer, 
          INTERNET_DEFAULT_HTTP_PORT, 
          NULL, 
          NULL,hg 
          INTERNET_SERVICE_HTTP, 
          0, 
          1); // Connection handle's Context 
    if (!hConnect) 
    { 
     if (GetLastError() != ERROR_IO_PENDING) 
     { 
      DWORD errorNum = GetLastError(); 
      fprintf(stderr, "InternetConnect Failed! Windows Error %d\n", errorNum); 
      InternetCloseHandle(hInstance); 
      return false; 
     } 
     // Wait until we get the connection handle 
     WaitForSingleObject(hConnectedEvent, INFINITE); 
    } 


    // Open the request 
    hRequest = HttpOpenRequest(hConnect, "GET", lpszUrl, NULL, NULL, NULL, 
          INTERNET_FLAG_RELOAD | INTERNET_FLAG_NO_CACHE_WRITE, 
          2); // Request handle's context 
    if (!hRequest) 
    { 
     if (GetLastError() != ERROR_IO_PENDING) 
     { 
      DWORD errorNum = GetLastError(); 
      fprintf(stderr, "HttpOpenRequest Failed! Windows Error %d\n", errorNum); 
      InternetCloseHandle(hConnect); 
      InternetCloseHandle(hInstance);h 
      return false; 
     } 
     // Wait until we get the request handle 
     WaitForSingleObject(hRequestOpenedEvent, INFINITE); 
    } 

    // Send the request 
    if (!HttpSendRequest(hRequest, NULL, 0, NULL, 0)) 
    { 
     if (GetLastError() != ERROR_IO_PENDING) 
     { 
      DWORD errorNum = GetLastError(); 
      fprintf(stderr, "HttpSendRequest Failed! Windows Error %d\n", errorNum); 
      InternetCloseHandle(hRequest); 
      InternetCloseHandle(hConnect); 
      InternetCloseHandle(hInstance); 
      return false; 
     } 
    } 

    if (bVerbose) 
    { 
     printf("HttpSendRequest called successfully\n"); 
    } 

    WaitForSingleObject(hRequestCompleteEvent, INFINITE); 

    // Before downloading file... 
    // 1. Get the temp directory 
    if (!(tempDirBytes = GetTempPathA(MAX_PATH, tempPath))) 
    { 
     fprintf(stderr, "Could not get temporary directory\n"); 
     InternetCloseHandle(hRequest); 
     InternetCloseHandle(hConnect); 
     InternetCloseHandle(hInstance); 
     return false; 
    } 

    // 2. Get temp file name (full name: tempPath\temp.tmp) 
    srand(GetTickCount()); 
    sprintf(tempFileName, "%s\\%08X.tmp", tempPath, rand()); 

    // Error check the end of temp file name for ending double slash 
    if (tempFileName[bufsize] == '\\') 
     tempFileName[bufsize] = '\0'; 

    // 3. Create temp file 
    printf("Creating temp file %s\nto store %s\n", tempFileName, srcPath.c_str()); 
    tempFile = fopen(tempFileName, "wb");  // Open the file for writing 
    if (!tempFile) 
    { 
     DWORD errorNum = GetLastError(); 
     fprintf(stderr, "Could not create temp file! Error %d\n", errorNum); 
     InternetCloseHandle(hRequest); 
     InternetCloseHandle(hConnect); 
     InternetCloseHandle(hInstance); 
     return false; 
    } 
    printf("Done!\n\n"); 

    printf("------------------- Read the response -------------------\n"); 

    unsigned long n = 0; 
    unsigned long sum = 0; 

    printf("Copying %s\n to %s\n", srcPath.c_str(), tempFileName); 


    // WHERE THE MAGIC HAPPENS - AND WHERE EVERYTHING FAILS! 
    while (InternetReadFile(hRequest, lpszDataBuffer, dwSize, &dwRead) && !(bAllDone)) 
    { 
     if (dwRead != 0) 
     { 
      sum = 0; 
      fwrite(lpszDataBuffer, 1, dwRead, tempFile); 
      for (unsigned long i = 0; i < dwRead; ++i) 
      { 
       sum += lpszDataBuffer[i]; 
       sum %= 0xFFFF; 
      } 
      printf("Received 4KB block %d. Sum %04X\r", n++, sum); 
     } 
     else 
     { 
      bAllDone = TRUE; 
      printf("\n"); 
      break; 
     } 
    } 

    printf("\n\n------------------- Request Complete ----------------\n"); 



    fclose(tempFile);    // Done writing to file 
    tempFile = fopen(tempFileName, "rb"); // Reopen for reading 


    //Create the local file 
    printf("Creating local file %s\n", destPath); 
    localFile = fopen(destPath, "wb"); 
    if (!localFile) 
    { 
     DWORD errorNum = GetLastError(); 
     fprintf(stderr, "Could not create local file! Windows Error %d\n", errorNum); 
     fclose(tempFile); 
     remove(tempFileName);  // delete temporary file from machine 
     InternetCloseHandle(hRequest); 
     InternetCloseHandle(hConnect); 
     InternetCloseHandle(hInstance); 
     return false; 
    } 
    printf("Done!\n\n"); 


    // Copy the contents from the temp file to the local file 
    printf("Copying temp file %s contents\nto local file %s\n", tempFileName, destPath); 
    if (!copyFile(tempFile, localFile)) 
    { 
     DWORD errorNum = GetLastError(); 
     fprintf(stderr, "Could not copy temp file to local directory! Windows Error\n", errorNum); 
     fclose(tempFile); 
     remove(tempFileName);  // delete temporary file from machine 
     fclose(localFile); 
     InternetCloseHandle(hRequest); 
     InternetCloseHandle(hConnect); 
     InternetCloseHandle(hInstance); 
     return false; 
    } 
    printf("Done!\n\n"); 






    // end of logic housekeeping 
    fclose(tempFile); 

    printf("Deleting temp file %s\n", tempFileName); 
    remove(tempFileName); // delete temporary file from machine 
    printf("Done!\n\n"); 

    fclose(localFile); 

    printf("Ending Internet Session\n"); 
    InternetCloseHandle(hRequest); 
    InternetCloseHandle(hConnect); 
    InternetCloseHandle(hInstance); 
    printf("Done!\n"); 

    printf("Press Enter to continue\n"); 
    std::cin.get(); 


    return true; 
} 
+0

您能否加載完整的代碼以便其他人可以試用?有一些丟失的文件,如httpfileretrieval.h。如果代碼已準備好構建,那麼對於其他開發人員來說,理解並提出他們的意見和建議會更有幫助。謝謝。 – 2013-01-22 18:29:59

+0

也發生在我身上:以愚蠢的代價爲代價,我分享了它對我不起作用的原因。如果您在獲得所有數據後調用它,它也不起作用。 – reallynice

回答

2

您的代碼爲我工作。你確定服務器正在返回一個非空的響應嗎?你可以使用像Fiddler2這樣的工具來檢查。這段代碼中有很多問題,包括緩衝區溢出:lpszDataBuffer[bufsize] = '\0';。另外,您正在使用異步模式,但在讀取循環中沒有任何異步處理。我建議您在此發佈代碼以供查看:https://codereview.stackexchange.com/

最後一個注意事項。如果你只是等待每一個操作完成,那麼異步執行操作沒有任何好處。你可以離開INTERNET_FLAG_ASYNC標誌。這會讓你的功能更簡單。

+0

謝謝你回答彼得。是的,你對'INTERNET_FLAG_ASYNC'的標誌絕對正確。我原本是爲了讓用戶在控制檯上提供交互式輸出來查看後臺發生了什麼,但我決定只是沿着程序的邏輯順序輸出。我拿走那面旗子的那一刻,一切都像魅力一樣。謝謝你的幫助! – Danchez