int WINAPI _DownloadServerFile( IN HANDLE hFile, IN DWORD dwFileServerSize, IN LPCTSTR pszURL, IN BOOL isFileExist )
{
HINTERNET hInternet = NULL;
HINTERNET hConnect = NULL;
HINTERNET hRequest = NULL;
int result;
DWORD dwSize, dwRead, dwWritten, dwTotalWrittenBytes;
LPBYTE pbBuffer = NULL, pbTemp = NULL;
DWORD dwBufferSize, dwNewSize;
int nStatusCode;
int nBufferPos;
clock_t lStartClock, lEndClock, lDuration;
BYTE baHeader[ 128 ];
URL_COMPONENTS stURLComponents;
TCHAR szSchemeName[ INTERNET_MAX_SCHEME_LENGTH ];
TCHAR szHostName[ INTERNET_MAX_HOST_NAME_LENGTH ];
TCHAR szUserName[ INTERNET_MAX_USER_NAME_LENGTH ];
TCHAR szPassword[ INTERNET_MAX_PASSWORD_LENGTH ];
TCHAR szURLPath[ INTERNET_MAX_URL_LENGTH ];
DWORD dwServiceType, dwFlag;
TCHAR szEncodedURL[ 4096 ];
TCHAR szHeader[ 1024 ];
DWORD dwFileSize, dwCurrentPos, dwStartBytes;
//------------------------------------------------------------------------
//
// URL 파싱
//
//------------------------------------------------------------------------
ZeroMemory( &stURLComponents, sizeof( URL_COMPONENTS ) );
stURLComponents.dwStructSize = sizeof( URL_COMPONENTS );
stURLComponents.lpszScheme = szSchemeName;
stURLComponents.dwSchemeLength = INTERNET_MAX_SCHEME_LENGTH;
stURLComponents.lpszHostName = szHostName;
stURLComponents.dwHostNameLength = INTERNET_MAX_HOST_NAME_LENGTH;
stURLComponents.lpszUserName = szUserName;
stURLComponents.dwUserNameLength = INTERNET_MAX_USER_NAME_LENGTH;
stURLComponents.lpszPassword = szPassword;
stURLComponents.dwPasswordLength = INTERNET_MAX_PASSWORD_LENGTH;
stURLComponents.lpszUrlPath = szURLPath;
stURLComponents.dwUrlPathLength = INTERNET_MAX_URL_LENGTH;
::URLEncode( pszURL, szEncodedURL, 4096 );
result = InternetCrackUrl( szEncodedURL, _tcslen( szEncodedURL ), 0, &stURLComponents );
if( result == FALSE )
{
DEBUGINFO( _T( "pszPreURL = %s" ), pszURL );
result = ERRORMSG( GetLastError(), _T( "Can not parse URL" ) );
STACKTRACE( _T( "InternetCrackUrl()" ) );
goto finish;
}
hInternet = InternetOpen( _T( "libAPI" ), INTERNET_OPEN_TYPE_PRECONFIG, NULL, NULL, 0 );
if( hInternet == NULL )
{
result = ERRORMSG( GetLastError(), _T( "Can not open internet session" ) );
STACKTRACE( _T( "InternetOpen()" ) );
goto finish;
}
dwFlag = INTERNET_FLAG_DONT_CACHE;
switch( stURLComponents.nScheme )
{
case INTERNET_SERVICE_HTTP:
dwServiceType = INTERNET_SERVICE_HTTP;
break;
case INTERNET_SCHEME_FTP:
dwServiceType = INTERNET_SERVICE_FTP;
break;
case INTERNET_SCHEME_GOPHER:
dwServiceType = INTERNET_SERVICE_GOPHER;
break;
case INTERNET_SCHEME_HTTPS:
dwServiceType = INTERNET_SERVICE_HTTP;
dwFlag |= INTERNET_FLAG_SECURE;
break;
default:
dwServiceType = INTERNET_SERVICE_HTTP;
break;
}
//------------------------------------------------------------------------
//
// 파일이 이미 존재하고 이어받기를 선택한 경우
//
//------------------------------------------------------------------------
dwStartBytes = 0;
if( ( isFileExist == TRUE ) && ( m_nWriteOption == NCG_WRITE_CONTINUE ) )
{
dwCurrentPos = SetFilePointer( m_hFileHandle, 0, 0, FILE_CURRENT );
dwFileSize = GetFileSize( m_hFileHandle, NULL );
dwStartBytes = dwFileSize - dwCurrentPos;
if( dwStartBytes >= dwFileServerSize )
{
OnTransfer( dwFileServerSize, dwFileServerSize );
OnEnd( 0 );
result = 0;
goto finish;
}
else
{
_stprintf( szHeader, _T( "Range: bytes=%d-" ), dwStartBytes );
SetFilePointer( m_hFileHandle, 0, 0, FILE_END );
}
}
else
{
szHeader[ 0 ] = 0;
}
hConnect = InternetConnect( hInternet,
szHostName,
stURLComponents.nPort,
NULL,
NULL,
dwServiceType,
dwFlag,
NULL );
if( hConnect == NULL )
{
result = ERRORMSG( GetLastError(), _T( "Can not connect host" ) );
STACKTRACE( _T( "InternetOpenUrl()" ) );
goto finish;
}
hRequest = HttpOpenRequest( hConnect, _T( "GET" ), stURLComponents.lpszUrlPath, NULL, NULL, NULL, INTERNET_FLAG_NO_CACHE_WRITE, NULL );
if( hRequest == NULL )
{
goto finish;
}
//------------------------------------------------------------------------
//
// 웹서버에 데이타를 전송
//
//------------------------------------------------------------------------
result = HttpSendRequest( hRequest, szHeader, _tcslen( szHeader ), 0, 0 );
if( result == FALSE )
{
result = ERRORMSG( GetLastError(), _T( "Can not request URL" ) );
STACKTRACE( _T( "HttpSendRequest()" ) );
goto finish;
}
dwSize = sizeof( baHeader );
result = HttpQueryInfo( hRequest, HTTP_QUERY_STATUS_CODE, baHeader, &dwSize, NULL );
if( result == FALSE )
{
result = ERRORMSG( GetLastError(), _T( "HTTP 헤더로부터 상태 코드를 가져올 수 없습니다" ) );
STACKTRACE( _T( "HttpQueryInfo()" ) );
goto finish;
}
nStatusCode = _ttoi( (LPCTSTR)baHeader );
if( nStatusCode == 404 )
{
//
// 못찾았다
// 그냥 스킵
//
result = ERRORMSG( ERROR_NOT_FOUND, _T( "%s URL에 파일이 존재하지 않습니다" ), pszURL );
goto finish;
}
else if( ( nStatusCode != 200 ) && ( nStatusCode != 304 ) && ( nStatusCode != 206 ) )
{
result = ERRORMSG( ERROR_HTTP_INVALID_QUERY_REQUEST,
_T( "%d is invalid response from web server" ), nStatusCode );
goto finish;
}
dwTotalWrittenBytes = 0;
nBufferPos = 0;
//------------------------------------------------------------------------
//
// 초기 버퍼 크기를 10K byte 로 잡는다.
//
//------------------------------------------------------------------------
dwBufferSize = 10240;
pbBuffer = new BYTE[ dwBufferSize ];
if( pbBuffer == NULL )
{
result = ERRORMSG( ERROR_NOT_ENOUGH_MEMORY, NULL );
DEBUGINFO( _T( "dwBufferSize = %d" ), dwBufferSize );
goto finish;
}
lStartClock = clock();
if( dwStartBytes != 0 )
{
dwWritten = dwTotalWrittenBytes = dwStartBytes;
OnTransfer( dwWritten, dwTotalWrittenBytes );
}
do
{
if( m_bDownloadCancel == TRUE )
{
TRACE( _T( "User canceled downloading. so return" ) );
result = ERROR_CANCELLED;
goto finish;
}
result = InternetQueryDataAvailable( hRequest, &dwSize, 0, 0 );
IF_TRUE_GOTO( result == FALSE, GetLastError() );
if( nBufferPos + dwSize > dwBufferSize )
{
//------------------------------------------------------------------------
//
// 1초가 안되었는데 버퍼가 풀이다
//
//------------------------------------------------------------------------
dwNewSize = dwBufferSize + dwSize;
pbTemp = new BYTE[ dwNewSize ];
if( pbTemp == NULL )
{
result = ERRORMSG( ERROR_NOT_ENOUGH_MEMORY, NULL );
DEBUGINFO( _T( "dwBufferSize = %d" ), dwNewSize );
goto finish;
}
CopyMemory( pbTemp, pbBuffer, dwBufferSize );
dwBufferSize = dwNewSize;
delete[] pbBuffer;
pbBuffer = pbTemp;
}
result = InternetReadFile( hRequest, &pbBuffer[ nBufferPos ], dwSize, &dwRead );
IF_TRUE_GOTO( result == FALSE, GetLastError() );
nBufferPos += dwRead;
if( dwRead == 0 )
{
break;
}
lEndClock = clock();
lDuration = ( lEndClock - lStartClock ) / CLOCKS_PER_SEC;
//------------------------------------------------------------------------
//
// 버퍼를 다 채우지 못하고 1초가 넘었다. 파일에 쓴다
//
//------------------------------------------------------------------------
if( lDuration >= 1 )
{
result = WriteFile( hFile, pbBuffer, nBufferPos, &dwWritten, NULL );
IF_TRUE_GOTO( result == FALSE, GetLastError() );
nBufferPos = 0;
dwTotalWrittenBytes += dwWritten;
lStartClock = clock();
OnTransfer( dwWritten, dwTotalWrittenBytes );
}
} while( dwRead != 0 );
//------------------------------------------------------------------------
//
// 아직 파일에 쓰지 못한 여분이 남아 있다면 파일에 쓰고 종료
//
//------------------------------------------------------------------------
if( nBufferPos != 0 )
{
result = WriteFile( hFile, pbBuffer, nBufferPos, &dwWritten, NULL );
IF_TRUE_GOTO( result == FALSE, GetLastError() );
dwTotalWrittenBytes += dwWritten;
OnTransfer( dwWritten, dwTotalWrittenBytes );
}
result = 0;
finish:
if( result != 0 )
{
STACKTRACE( _T( "_DownloadServerFile" ) );
}
if( hRequest != NULL )
{
InternetCloseHandle( hRequest );
}
if( hConnect != NULL )
{
InternetCloseHandle( hConnect );
}
if( hInternet != NULL )
{
InternetCloseHandle( hInternet );
}
if( pbBuffer != NULL )
{
delete[] pbBuffer;
}
return result;
}
//OnTransfer OnEnd OnBegin은 프로그레스바 및 상태를 나타내기 위한 인터페이스 함수이다.
댓글 없음:
댓글 쓰기