2013-01-21 2 views
1

Я новый парень на сайте здесь, поэтому простите меня, если я сделаю что-то не так в этом посте.InternetReadFile(), похоже, не читает данные в Интернете

Я работаю с WinINet и пытаюсь загрузить binary file из Интернета, но по какой-то причине, когда я добираюсь до точки фактически загрузок этого файла с помощью InternetReadFile(), он возвращает не читает вообще ничего (0 байт считывание информации). Запуск Visual Studio 2012 debugger показал мне эту деталь, потому что обработчик HINTERNET, который я передаю в вызов API, определенно имеет данные точно. Я просто не понимаю, что я делаю неправильно. Может быть, вы, ребята, можете помочь?

Основной смысл моей программы в том, что я загружаю двоичный файл из сети и сохраняю его во временный файл, находящийся во временном каталоге. После копирования содержимого во временный файл я передаю содержимое двоичных данных этого временного файла в другой локальный файл (на этот раз в пределах допустимого каталога). Вот что я до сих пор. Надеюсь, с логикой пробое я обеспечиваю, вы, ребята, будете иметь возможность следить за его несмотря на длину кода ...

#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. Если код готов к построению, для другого разработчика будет более полезно понимать и делать свои комментарии и предложения. Благодарю. –

+0

Мне тоже повезло: по цене глядя глупо, я разделяю причину, по которой это не сработало для меня. Он не будет работать, если вы вызовете его после того, как у вас уже есть все данные. – reallynice

ответ

2

Ваш код работает для меня. Вы уверены, что сервер возвращает непустой ответ? Вы можете использовать инструмент Fiddler2 для проверки. В этом коде есть немало проблем, включая переполнение буфера здесь: lpszDataBuffer[bufsize] = '\0';. Кроме того, вы используете асинхронный режим, но у вас нет асинхронной обработки в вашем цикле чтения. Я рекомендую вам опубликовать код для просмотра здесь: https://codereview.stackexchange.com/.

В заключение. Если вы просто будете ждать завершения каждой операции, то нет никакой пользы для асинхронности. Вы можете оставить флаг INTERNET_FLAG_ASYNC. Это сделает вашу функцию намного проще.

+0

Спасибо, что ответили Петром. Да, вы определенно были правы относительно флага «INTERNET_FLAG_ASYNC». Первоначально мне приходилось предоставлять интерактивный выход на консоли, чтобы пользователь мог видеть, что происходит в фоновом режиме, но я решил просто иметь последовательный вывод по логике программы. В тот момент, когда я удалил этот флаг, все работало как шарм. Спасибо за вашу помощь! – Danchez

Смежные вопросы