예전에 만들어 놓은 것이 있는데.. 도통 찾을 수가 없어서 다시 만들어 본 함수입니다. 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가 필요합니다.