예전에 만들어 놓은 것이 있는데.. 도통 찾을 수가 없어서 다시 만들어 본 함수입니다. URL 경로에 존재하는 데이터를 다운로드하여 로컬 파일로 저장해 주는 함수입니다. 실제 개발에 사용할 요량으로 인자가 제법 복잡합니다.
DWORD Download(HINTERNET hInternet, char *pszURL,
char *pszFileName, BYTE *pBuffer) {
HINTERNET hURL = InternetOpenUrl(hInternet, pszURL, NULL, 0, 0, 0);
if(hURL == NULL) {
InternetCloseHandle(hInternet);
return -2;
}
HANDLE hFile = CreateFile(pszFileName, GENERIC_WRITE, 0,
NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
if(hFile == INVALID_HANDLE_VALUE) return -3;
DWORD dwSize = 2048;
DWORD dwRead, dwWritten, dwTotalSize;
bool bOK = HttpQueryInfo(hURL, HTTP_QUERY_CONTENT_LENGTH,
pBuffer, &dwRead, NULL);
if(!bOK) return -4;
dwTotalSize = atoi((const char *)pBuffer);
do {
InternetQueryDataAvailable(hURL, &dwSize, 0, 0);
InternetReadFile(hURL, pBuffer, dwSize, &dwRead);
WriteFile(hFile, pBuffer, dwRead, &dwWritten, NULL);
} while(dwRead != 0);
InternetCloseHandle(hURL);
CloseHandle(hFile);
return dwTotalSize;
}
아래는 위의 함수를 직접 사용하는 코드입니다.
HINTERNET hInternet = InternetOpen("MyAGENT", INTERNET_OPEN_TYPE_PRECONFIG,
NULL, NULL, 0);
if(hInternet == NULL) return 0;
BYTE *pBuffer = new BYTE[1024*1024];
DWORD dwTotalSize;
dwTotalSize = Download(hInternet, "http://www.s.com/a.zip", "c:/a.zip", pBuffer);
printf("TotalSize: %d\n", dwTotalSize);
dwTotalSize = Download(hInternet, "http://www.s.com/b.zip", "c:/b.zip", pBuffer);
printf("TotalSize: %d\n", dwTotalSize);
delete [] pBuffer;
InternetCloseHandle(hInternet);
1번 코드에서처럼 가장먼저 hInternet 객체를 만듭니다. 이 객체를 재활용하여 다수의 URL을 통해 파일을 다운로드할 수 있습니다. 5번 코드는 파일을 다운로드하는데 사용하는 버퍼입니다. Download 함수를 여러번 사용할 것을 대비하여 버퍼를 재활용할 수 있도록 하였습니다. 또한 Downoad 함수의 결과값은 다운로드된 바이너리 데이터의 전체 바이트 수입니다. 음수인 경우 ERROR로 간주할 수 있습니다. 14번과 15번 코드처럼 사용한 리소스는 반환합니다.
추가로 아래의 Download2 함수는 다운로드된 데이터를 파일로 기록하지 않고 메모리 버퍼에 저장하는 함수입니다. 다운로드된 데이터를 파일에 저장하지 않고 바로 메모리 상에서 사용하고자 할때 사용할 수 있습니다.
DWORD Download2(HINTERNET hInternet, char *pszURL, BYTE *pBuffer) {
HINTERNET hURL = InternetOpenUrl(hInternet, pszURL, NULL, 0, 0, 0);
if(hURL == NULL) {
InternetCloseHandle(hInternet);
return -2;
}
DWORD dwSize;
DWORD dwRead, dwWritten, dwTotalSize;
DWORD dwCursor = 0;
bool bOK = HttpQueryInfo(hURL, HTTP_QUERY_CONTENT_LENGTH, pBuffer,
&dwRead, NULL);
if(!bOK) return -4;
dwTotalSize = atoi((const char *)pBuffer);
do {
InternetQueryDataAvailable(hURL, &dwSize, 0, 0);
InternetReadFile(hURL, (LPVOID)(pBuffer + dwCursor), dwSize, &dwRead);
dwCursor += dwRead;
} while(dwRead != 0);
InternetCloseHandle(hURL);
return dwTotalSize;
}
끝으로 이 함수 사용을 위해 헤더 파일로 wininet.h와 라이브러리 파일로 wininet.lib가 필요합니다.