2013-01-21 2 views
1

저는이 웹 사이트에서 새로운 사람입니다.이 게시물에서 잘못된 것이 있으면 용서해주십시오.InternetReadFile()이 인터넷 데이터를 읽지 않는 것 같습니다.

실제로 InternetReadFile()을 사용하여 해당 파일을 다운로드하는 지점에 도착했을 때 어떤 이유로, WinINet 작업 및 인터넷에서 binary file 다운로드를 시도하지만있어, 그것은 아무 것도 읽을하지 반환 (정보의 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와 같은 누락 된 파일이 있습니다. 코드를 빌드 할 준비가되면 다른 개발자가 자신의 의견과 제안을 이해하고 이해하는 데 더 도움이 될 것입니다. 감사. –

+0

나에게도 일어났다. 멍청한 짓을하는 댓가로 나에게 그게 효과가 없었던 이유를 나눈다. 이미 모든 데이터를 가져온 후에도 호출하면 작동하지 않습니다. – reallynice

답변

2

귀하의 코드는 나를 위해 작동 ... 코드의 길이에도 불구하고 그것을 수행 할 수 있습니다. 서버가 비어 있지 않은 응답을 반환하고 있습니까? Fiddler2와 같은 도구를 사용하여 확인할 수 있습니다. 이 코드에는 버퍼 오버런을 포함하여 몇 가지 문제가 있습니다 (lpszDataBuffer[bufsize] = '\0';). 또한 비동기 모드를 사용하고 있지만 읽기 루프에는 비동기 처리가 없습니다. 리뷰 코드를 여기에 게시 하시길 권장합니다 : https://codereview.stackexchange.com/.

마지막주의 사항. 어쨌든 각 작업이 완료 될 때까지 기다리려면 비동기식으로 작업 할 때 이점이 없습니다. INTERNET_FLAG_ASYNC 깃발을 벗어날 수 있습니다. 이렇게하면 함수가 훨씬 간단 해집니다.

+0

피터에게 답변 해 주셔서 감사합니다. 네, 당신은 'INTERNET_FLAG_ASYNC'플래그에 대해 확실히 옳았습니다. 원래 사용자가 콘솔에서 대화 형 출력을 제공하여 사용자가 백그라운드에서 진행중인 작업을 볼 수있게했지만 프로그램의 논리에 따라 순차적 출력 만하기로 결정했습니다. 그 깃발을 제거하는 순간 모든 것이 매력처럼 작동했습니다. 당신의 도움을 주셔서 감사합니다! – Danchez

관련 문제