2011-08-05 6 views
2

현재 간단한 프로그램을 프로그래밍 중이므로 친구에게 배포하고 싶습니다. 내가 성취하고자하는 것은 프로그램을 시작할 때 인터넷에서 버퍼에 외부 바이너리 파일을 작성하는 것입니다. 이렇게하려면 Windows 인터넷 (wininet)을 사용하고 있습니다. 현재 InternetReadFile을 사용하여 프로그램에서 나중에 사용하는 버퍼에 파일을 씁니다. 그러나 File이 완전히 읽히지 않는 경우, 결과 크기가 서버의 파일 크기보다 훨씬 작을 때와 같아야합니다.Wininet을 사용하여 이진 파일 다운로드

외부 라이브러리를 사용하지 않고이 작업을 수행하고 싶습니다.

내 문제를 해결할 수있는 아이디어가 있습니까?

덕분에, 앤드류

+0

편집 내 대답은 전체 작업 프로그램을 포함합니다. 그것을 시험해보고 효과가 있는지 확인할 수 있습니까? –

답변

7

documentation 다음과 같은 말을한다 :

InternetReadFile을 몇 가지 예외를 제외하고, 많은 기본 ReadFile을 기능처럼 작동합니다. 일반적으로 InternetReadFile은 HINTERNET 핸들에서 순차적 인 바이트 스트림으로 데이터를 검색합니다. InternetReadFile 호출마다 읽을 데이터 양은 dwNumberOfBytesToRead 매개 변수로 지정되며 데이터는 lpBuffer 매개 변수로 반환됩니다. 정상적인 읽기는 파일 끝에 도달 할 때까지 InternetReadFile에 대한 각 호출에 대해 지정된 dwNumberOfBytesToRead를 검색합니다. 모든 데이터가 검색되도록하려면 함수가 TRUE를 반환하고 lpdwNumberOfBytesRead 매개 변수가 0이 될 때까지 응용 프로그램에서 InternetReadFile 함수를 계속 호출해야합니다.

기본적으로 정확하게 읽을 기능이 있다는 것을 보증하지 않습니다. dwNumberOfBytesToRead. lpdwNumberOfBytesRead 매개 변수를 사용하여 실제로 읽은 바이트 수를 확인하십시오.

또한 전체 파일 크기가 dwNumberOfBytesToRead보다 커지면 호출을 여러 번 호출해야합니다. 한 번에 dwNumberOfBytesToRead 개를 읽지 못하기 때문입니다. 당신이 그것을 축적 대신에 다른 파일에 버퍼의 데이터를 기록 할 필요가

::DWORD error = ERROR_SUCCESS; 
::BYTE data[SIZE]; // total file size. 
::DWORD size = 0; 
::DWORD read = 0; 
do { 
    ::BOOL result = ::InternetReadFile(stream, data+size, SIZE-size, &read); 
    if (result == FALSE) { 
     error = ::GetLastError(); 
    } 
} 
while ((error == ERROR_SUCCESS) && (read > 0) && ((size+=read) < SIZE)); 
    // check that `SIZE` was correct. 
if (size != SIZE) { 
} 

그렇지 않으면 : 당신이 사전에 전체 파일 크기가있는 경우

은 루프는 다음과 같은 형식을 취합니다.

EDIT (샘플 테스트 프로그램) :

여기에 StackOverflow의 첫 페이지를 가져 완벽한 프로그램입니다. 이렇게하면 1K 청크에 약 200K 개의 HTML 코드가 다운로드되고 전체 페이지가 검색됩니다. 이것을 실행할 수 있고 작동하는지 확인할 수 있습니까?

#include <Windows.h> 
#include <Wininet.h> 
#include <iostream> 
#include <fstream> 

namespace { 

    ::HINTERNET netstart() 
    { 
     const ::HINTERNET handle = 
      ::InternetOpenW(0, INTERNET_OPEN_TYPE_DIRECT, 0, 0, 0); 
     if (handle == 0) 
     { 
      const ::DWORD error = ::GetLastError(); 
      std::cerr 
       << "InternetOpen(): " << error << "." 
       << std::endl; 
     } 
     return (handle); 
    } 

    void netclose (::HINTERNET object) 
    { 
     const ::BOOL result = ::InternetCloseHandle(object); 
     if (result == FALSE) 
     { 
      const ::DWORD error = ::GetLastError(); 
      std::cerr 
       << "InternetClose(): " << error << "." 
       << std::endl; 
     } 
    } 

    ::HINTERNET netopen (::HINTERNET session, ::LPCWSTR url) 
    { 
     const ::HINTERNET handle = 
      ::InternetOpenUrlW(session, url, 0, 0, 0, 0); 
     if (handle == 0) 
     { 
      const ::DWORD error = ::GetLastError(); 
      std::cerr 
       << "InternetOpenUrl(): " << error << "." 
       << std::endl; 
     } 
     return (handle); 
    } 

    void netfetch (::HINTERNET istream, std::ostream& ostream) 
    { 
     static const ::DWORD SIZE = 1024; 
     ::DWORD error = ERROR_SUCCESS; 
     ::BYTE data[SIZE]; 
     ::DWORD size = 0; 
     do { 
      ::BOOL result = ::InternetReadFile(istream, data, SIZE, &size); 
      if (result == FALSE) 
      { 
       error = ::GetLastError(); 
       std::cerr 
        << "InternetReadFile(): " << error << "." 
        << std::endl; 
      } 
      ostream.write((const char*)data, size); 
     } 
     while ((error == ERROR_SUCCESS) && (size > 0)); 
    } 

} 

int main (int, char **) 
{ 
    const ::WCHAR URL[] = L"http://stackoverflow.com/"; 
    const ::HINTERNET session = ::netstart(); 
    if (session != 0) 
    { 
     const ::HINTERNET istream = ::netopen(session, URL); 
     if (istream != 0) 
     { 
      std::ofstream ostream("output.txt", std::ios::binary); 
      if (ostream.is_open()) { 
       ::netfetch(istream, ostream); 
      } 
      else { 
       std::cerr << "Could not open 'output.txt'." << std::endl; 
      } 
      ::netclose(istream); 
     } 
     ::netclose(session); 
    } 
} 

#pragma comment (lib, "Wininet.lib") 
+0

답장을 보내 주셔서 감사합니다. 나는 TrueRead가 반환 될 때까지 while 루프에서 InternetReadFile을 호출했지만 파일은 여전히 ​​손상되어 적절한 크기가 아닙니다. – Andrew

+0

@Andrew : 설명서를 다시 읽으십시오. "TRUE"는 "성공"조건 ("단지 1 바이트의 데이터 읽기"포함)로 반환됩니다. 처음에는'TRUE'를 반환해야하므로 'TRUE'를 반환 할 때까지 반복하지 마십시오. –

+0

@Andrew : 데이터를 아무 곳이나 복사하지 않고 함수에서 반환 한 총 바이트 수만 계산 했습니까? 이것이 시작하기에 적절한 바이트 수를 리턴하는지 확인하십시오. –

관련 문제