-
HTTP - Win32Platform/소켓 2009. 2. 13. 20:30웹서버만 있으면 된다.
Windows Internet API(WinINet API)
HTTP
FTP
gopher
서버를 만드는 데는 사용할 수 없다
wininet.dll
#include <wininet.h>
InternetOpen()
INTERNET_OPEN_TYPE_PRECONFIGInternetConnect()
INTERNET_DEFAULT_HTTP_PORT
INTERNET_SERVICE_HTTP
InternetOpenUrl()INTERNET_FLAG_DONT_CACHEHttpQueryInfo()
InternetCloseHandle()
InternetQueryDataAvailable()
InternetReadFile()
요청한 크기보다 작을 수 있다.HttpOpenRequest()
파일 이름에 한글이 포함된 경우 UTR-8로 변환 후 URL 인코딩을 한다.(이것 땜에 사경을 헤맸네..)
HttpEndRequest()
HttpAddRequestHeaders()
HttpSendRequest()
HttpSendRequestEx()
InternetWriteFile()
InternetCrackUrl()
HttpQueryInfo()
InternetSetFilePointer()
로컬 PC의 캐시에 적용되기 때문에 큰 파일에는 사용하면 안될 것 같음 // ???
InternetSetStatusCallback()
InternetGetCookie()
InternetSetCookie()
InternetSetOption()
InternetQueryOption()
<!-- my_form.html -->
<form action="my_form_action.php" method="post">
<p>이름: <input type="text" name="name" /></p>
<p>연령: <input type="text" name="age" /></p>
<p><input type="submit" /></p>
</form>
<!-- my_form_action.php -->
<?php echo htmlspecialchars($_POST['name']); ?>씨 안녕하세요.
당신은 <?php echo (int)$_POST['age']; ?>세입니다.
#include <windows.h>
#include <tchar.h>
#include <wininet.h>
#pragma comment(lib, "wininet")
int main(int argc, char* argv[])
{
// {
static LPSTR accept[2]={"*/*", NULL};
static TCHAR hdrs[] = _T("Content-Type: application/x-www-form-urlencoded");
static TCHAR frmdata[] = _T("name=aaa&age=22");
static char buf[4096];
DWORD dwRead;
HINTERNET hSession = InternetOpen("MyAgent",
INTERNET_OPEN_TYPE_PRECONFIG, NULL, NULL, 0);
if(hSession == NULL) {
...
return 1;
}
HINTERNET hConnect = InternetConnect(hSession, _T("localhost"),
INTERNET_DEFAULT_HTTP_PORT, NULL, NULL, INTERNET_SERVICE_HTTP, 0, 0);
HINTERNET hRequest = HttpOpenRequest(hConnect, "POST",
_T("/my_form_action.php"), NULL, NULL, const_cast<LPCSTR *>(&accept[0]), 0, 0);
HttpSendRequest(hRequest, hdrs, strlen(hdrs), frmdata, strlen(frmdata));
do {
// InternetQueryDataAvailable(hReq, &size,0,0);
InternetReadFile(hRequest,buf,sizeof(buf)-1,&dwRead);
buf[dwRead] = 0;
puts(buf);
} while(dwRead != 0);
// puts("\n");
InternetCloseHandle(hRequest);
InternetCloseHandle(hConnect);
InternetCloseHandle(hSession);
// }
// printf("Hello World!\n");
return 0;
}#include<windows.h>
#include<wininet.h>
#include<iostream.h>
void main(int argc, char *argv[])
{
if (argc != 3)
{
cout << "Usage: progress <host> <object>" << endl;
return;
}
HINTERNET hSession = InternetOpen("WinInet Progress Sample",
INTERNET_OPEN_TYPE_PRECONFIG,
NULL,
NULL,
0);
HINTERNET hConnection = InternetConnect(hSession,
argv[1], // Server
INTERNET_DEFAULT_HTTP_PORT,
NULL, // Username
NULL, // Password
INTERNET_SERVICE_HTTP,
0, // Synchronous
NULL); // No Context
HINTERNET hRequest = HttpOpenRequest(hConnection,
"GET",
argv[2],
NULL, // Default HTTP Version
NULL, // No Referer
(const char**)"*/*\0", // Accept
// anything
0, // Flags
NULL); // No Context
HttpSendRequest(hRequest,
NULL, // No extra headers
0, // Header length
NULL, // No Body
0); // Body length
DWORD dwContentLen;
DWORD dwBufLen = sizeof(dwContentLen);
if (HttpQueryInfo(hRequest,
HTTP_QUERY_CONTENT_LENGTH | HTTP_QUERY_FLAG_NUMBER,
(LPVOID)&dwContentLen,
&dwBufLen,
0))
{
// You have a content length so you can calculate percent complete
char *pData = (char*)GlobalAlloc(GMEM_FIXED, dwContentLen + 1);
DWORD dwReadSize = dwContentLen / 10; // We will read 10% of data
// with each read.
cout << "Download Progress:" << endl;
cout << " 0----------100%" << endl;
cout << " ";
cout.flush();
DWORD cReadCount;
DWORD dwBytesRead;
char *pCopyPtr = pData;
for (cReadCount = 0; cReadCount < 10; cReadCount++)
{
InternetReadFile(hRequest, pCopyPtr, dwReadSize, &dwBytesRead);
cout << "*";
cout.flush();
pCopyPtr = pCopyPtr + dwBytesRead;
}
// extra read to account for integer division round off
InternetReadFile(hRequest,
pCopyPtr,
dwContentLen - (pCopyPtr - pData),
&dwBytesRead);
// Null terminate data
pData[dwContentLen] = 0;
// Display
cout << endl << "Download Complete" << endl;
cout << pData;
}
else
{
DWORD err = GetLastError();
// No content length...impossible to calculate % complete
// Just read until we are done.
char pData[100];
DWORD dwBytesRead = 1;
while (dwBytesRead)
{
InternetReadFile(hRequest, pData, 99, &dwBytesRead);
pData[dwBytesRead] = 0;
cout << pData;
}
}
}
BOOL GetFile (HINTERNET IN hOpen, // Handle from InternetOpen()
CHAR *szUrl, // Full URL
CHAR *szFileName) // Local file name
{
DWORD dwSize;
CHAR szHead[] = "Accept: */*\r\n\r\n";
VOID * szTemp[25];
HINTERNET hConnect;
FILE * pFile;
if ( !(hConnect = InternetOpenUrl ( hOpen, szUrl, szHead,
lstrlen (szHead), INTERNET_FLAG_DONT_CACHE, 0)))
{
cerr << "Error !" << endl;
return 0;
}
if ( !(pFile = fopen (szFileName, "wb" ) ) )
{
cerr << "Error !" << endl;
return FALSE;
}
do
{
// Keep coping in 25 bytes chunks, while file has any data left.
// Note: bigger buffer will greatly improve performance.
if (!InternetReadFile (hConnect, szTemp, 50, &dwSize) )
{
fclose (pFile);
cerr << "Error !" << endl;
return FALSE;
}
if (!dwSize)
break; // Condition of dwSize=0 indicate EOF. Stop.
else
fwrite(szTemp, sizeof (char), dwSize , pFile);
} // do
while (TRUE);
fflush (pFile);
fclose (pFile);
return TRUE;
}
static TCHAR hdrs[] =
_T("Content-Type: application/x-www-form-urlencoded");
static TCHAR frmdata[] =
_T("name=John+Doe&userid=hithere&other=P%26Q");
static LPSTR accept[2]={"*/*", NULL};
// for clarity, error-checking has been removed
HINTERNET hSession = InternetOpen("MyAgent",
INTERNET_OPEN_TYPE_PRECONFIG, NULL, NULL, 0);
HINTERNET hConnect = InternetConnect(hSession, _T("ServerNameHere"),
INTERNET_DEFAULT_HTTP_PORT, NULL, NULL, INTERNET_SERVICE_HTTP, 0, 1);
HINTERNET hRequest = HttpOpenRequest(hConnect, "POST",
_T("FormActionHere"), NULL, NULL, accept, 0, 1);
HttpSendRequest(hRequest, hdrs, strlen(hdrs), frmdata, strlen(frmdata));
// close any valid internet-handles
BOOL UseHttpSendReqEx(HINTERNET hConnect, TCHAR *upFile)
{
INTERNET_BUFFERS BufferIn = {0};
DWORD dwBytesRead;
DWORD dwBytesWritten;
BYTE pBuffer[1024]; // Read from file in 1K chunks
BOOL bRead, bRet;
BufferIn.dwStructSize = sizeof( INTERNET_BUFFERS );
HINTERNET hRequest = HttpOpenRequest (hConnect, "PUT",
"/test/page.htm", NULL, NULL, NULL, 0, 0);
if (!hRequest)
{
printf("Failed to open request handle: %lu\n", GetLastError ());
return FALSE;
}
HANDLE hFile = CreateFile (upFile, GENERIC_READ, FILE_SHARE_READ,
NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
if (hFile == INVALID_HANDLE_VALUE)
{
printf("\nFailed to open local file %s.", upFile);
return FALSE;
}
BufferIn.dwBufferTotal = GetFileSize (hFile, NULL);
printf ("File size is %d\n", BufferIn.dwBufferTotal );
if(!HttpSendRequestEx( hRequest, &BufferIn, NULL, HSR_INITIATE, 0))
{
printf( "Error on HttpSendRequestEx %lu\n",GetLastError() );
return FALSE;
}
DWORD sum = 0;
do
{
if (!(bRead = ReadFile (hFile, pBuffer, sizeof(pBuffer),
&dwBytesRead, NULL)))
{
printf ("\nReadFile failed on buffer %lu.",GetLastError());
break;
}
if (!(bRet=InternetWriteFile( hRequest, pBuffer, dwBytesRead,
&dwBytesWritten)))
{
printf ("\nInternetWriteFile failed %lu", GetLastError());
break;
}
sum += dwBytesWritten;
}
while (dwBytesRead == sizeof(pBuffer)) ;
CloseHandle (hFile);
printf ("Actual written bytes: %d\n", sum);
if(!HttpEndRequest(hRequest, NULL, 0, 0))
{
printf( "Error on HttpEndRequest %lu \n", GetLastError());
return FALSE;
}
return TRUE;
}
HINTERNET hHttpFile;
hHttpFile = InternetOpenUrl(NULL, 다운받을 압축파일(zip), NULL, 0, 0, 0 );
CInternetFile* pFile = (CInternetFile*)session.OpenURL(m_strFile);
char bufQuery[32] ;
DWORD dwLengthBufQuery = sizeof(bufQuery);
BOOL bQuery = ::HttpQueryInfo(hHttpFile, HTTP_QUERY_CONTENT_LENGTH, bufQuery, &dwLengthBufQuery, NULL) ;
DWORD dwFileSize = (DWORD)atol(bufQuery) ;
char* buffer = new char[dwFileSize+1] ;
DWORD dwBytesRead ;
BOOL bRead = ::InternetReadFile(hHttpFile, buffer, dwFileSize+1, &dwBytesRead);
::InternetCloseHandle(hHttpFile);
try {
pFile = (CInternetFile*)session.OpenURL(m_strFile); // 다운받을 Url
} catch(CInternetException* ){
MessageBox("사이트에 접속할수 없습니다..", "Update", MB_ICONSTOP);
return ;
}
if(pFile)
{
HUNZIP huz;
ZIPENTRY ze;
DWORD numitems;
SetDlgItemText (IDC_STATIC_MSG,"파일 다운로드 중");
int s = pFile->GetLength ();
int i = 0;
m_ctrProgress.Init (s);
file.Open(strLocalFile,CFile::modeCreate | CFile::modeWrite);
// pFile->SetReadBufferSize(4096);
char buf[4096] = {0};
while(pFile->Read(buf,sizeof(buf)))
{
i++;
m_ctrProgress.SetPos(i);
file.Write((LPCSTR)buf,sizeof(buf));
}
m_ctrProgress.SetPos (0);
file.Close();
Sleep(500);
SetDlgItemText (IDC_STATIC_MSG,"압축을 풀고있습니다");
if ((unzipDll = (HMODULE)LoadLibrary(_T("LiteUnZip.dll"))))
{
// Get the addresses of 5 functions in LiteUnzip.dll -- UnzipOpenFile(), UnzipGetItem()
// UnzipItemToFile(), UnzipClose(), and UnzipFormatMessage.
lpUnzipOpenFile = (UnzipOpenFilePtr *)GetProcAddress(unzipDll, UNZIPOPENFILENAME);
lpUnzipGetItem = (UnzipGetItemPtr *)GetProcAddress(unzipDll, UNZIPGETITEMNAME);
lpUnzipItemToFile = (UnzipItemToFilePtr *)GetProcAddress(unzipDll, UNZIPITEMTOFILENAME);
lpUnzipClose = (UnzipClosePtr *)GetProcAddress(unzipDll, UNZIPCLOSENAME);
lpUnzipFormatMessage = (UnzipFormatMessagePtr *)GetProcAddress(unzipDll, UNZIPFORMATMESSAGENAME);
// Open a ZIP archive on disk named "test.zip".
if (!(result = lpUnzipOpenFile(&huz, strLocalFile, 0)))
{
ZIPENTRY ze;
DWORD numitems;
// Find out how many items are in the archive.
ze.Index = (DWORD)-1;
if ((result = lpUnzipGetItem(huz, &ze))) goto bad3;
numitems = ze.Index;
m_ctrProgress.Init (numitems);
// Unzip each item, using the name stored (in the zip) for that item.
for (ze.Index = 0; ze.Index < numitems; ze.Index++)
{
tmp.Format ("%s",ze.Name);
int i = tmp.GetAllocLength ();
if(i > 20)
tmp.Delete (10,1);
SetDlgItemText (IDC_STATIC_MSG,tmp);
if ((result = lpUnzipGetItem(huz, &ze)) || (result = lpUnzipItemToFile(huz, ze.Name, &ze)))
{
bad3: lpUnzipClose(huz);
goto bad;
}
m_ctrProgress.SetPos (ze.Index+1);
Sleep (50);
}
// Done unzipping files, so close the ZIP archive.
lpUnzipClose(huz);
}
else
{
TCHAR msg[100];
bad4: lpUnzipFormatMessage(result, msg, sizeof(msg));
AfxMessageBox ("error");
}
FreeLibrary(unzipDll);
DeleteFile(strLocalFile);
SetDlgItemText (IDC_STATIC_MSG,"완료");
Sleep (500);
OnCancel ();
}
}
UINT DownloadThread(LPVOID pParam)
{
CDManager *pManager;
pManager = (CDManager *)pParam;
char szReadBuf[32768];
DWORD dwSize, dwRead, dwWritten = 0;
DWORD dwTotalBytes = 0;
HINTERNET m_hInternetSession, m_hHttpConnection;
m_hInternetSession = InternetOpen("HTTP", INTERNET_OPEN_TYPE_PRECONFIG, NULL, 0, 0);
if (m_hInternetSession == NULL)
{
pManager->m_ctrlWorkStatus.SetWindowText("Cannot connect to internet");
return -1;
}
m_hHttpConnection = InternetOpenUrl( m_hInternetSession,
pManager->m_csDownloadURL,
NULL,
0,
INTERNET_FLAG_RELOAD,
0);
if (m_hHttpConnection == NULL)
{
pManager->m_ctrlWorkStatus.SetWindowText("Cannot connect to Download URL");
InternetCloseHandle(m_hInternetSession);
return -1;
}
TCHAR szBuffer[MAX_PATH];
DWORD dwBufferSize = MAX_PATH;
DWORD dwIndex = 0;
BOOL bRes = HttpQueryInfo(m_hHttpConnection, HTTP_QUERY_CONTENT_LENGTH, szBuffer,
&dwBufferSize, &dwIndex);
if (!bRes)
{
pManager->m_ctrlWorkStatus.SetWindowText("Queryinfo Fail");
InternetCloseHandle(m_hInternetSession);
return 1;
}
DWORD dwFileSize = (DWORD)atol(szBuffer);
double dwDivide = ( 100 / (double)dwFileSize );
pManager->m_ctrlDProgress.SetRange32(0, dwFileSize);
CFile file;
CFileException e;
CString path;
path = pManager->m_csDefaultFolder + "\\" + pManager->m_csSaveFileName;
pManager->m_csFullPath = path;
if(pManager->m_nButton == 0)
{
// Relay-Download //
FILE *fp;
fp = fopen(path, "r");
if(fp == NULL)
{
// New File //
file.Open(path, CFile::modeCreate | CFile::modeWrite | CFile::shareDenyWrite, &e);
}
else
{
// Already Exist //
fclose(fp);
file.Open(path, CFile::modeRead, &e);
DWORD dwFileLength = file.GetLength();
file.Close();
// Reconnect //
InternetCloseHandle(m_hHttpConnection);
InternetCloseHandle(m_hInternetSession);
m_hInternetSession = InternetOpen("HTTP", INTERNET_OPEN_TYPE_PRECONFIG, NULL, 0, 0);
if (m_hInternetSession == NULL)
{
pManager->m_ctrlWorkStatus.SetWindowText("Cannot connect to internet");
return -1;
}
CString csAddHeader;
csAddHeader.Format("Range:bytes=%d-", dwFileLength);
m_hHttpConnection = InternetOpenUrl( m_hInternetSession,
pManager->m_csDownloadURL,
csAddHeader,
csAddHeader.GetLength(),
INTERNET_FLAG_RELOAD,
0);
if (m_hHttpConnection == NULL)
{
pManager->m_ctrlWorkStatus.SetWindowText("Cannot connect to Download URL");
InternetCloseHandle(m_hInternetSession);
return -1;
}
dwTotalBytes = dwFileLength;
file.Open(path, CFile::modeCreate | CFile::modeNoTruncate | CFile::modeWrite | CFile::shareDenyWrite, &e);
file.SeekToEnd();
}
}
else
{
file.Open(path, CFile::modeCreate | CFile::modeWrite | CFile::shareDenyWrite, &e);
}
// 파일을 생성합니다.
char sMsg[256];
DWORD dwStartTick, dwCurrentTick;
double fRate;
dwStartTick = GetTickCount();
do
{
if(!InternetQueryDataAvailable(m_hHttpConnection, &dwSize, 0, 0))
{
pManager->m_ctrlWorkStatus.SetWindowText("Data not Availiable");
return -1;
}
if(!InternetReadFile(m_hHttpConnection, szReadBuf, dwSize, &dwRead))
{
pManager->m_ctrlWorkStatus.SetWindowText("Reading File Fail");
return -1;
}
if (dwRead) // 읽고 싶은 양 만큼 1024 만큼 (예)
{
// 생성한 파일에 읽어 온만큼 파일을 씀니다.
dwCurrentTick = GetTickCount();
file.Write(szReadBuf, dwRead);
dwTotalBytes += dwRead;
fRate = (double)(dwTotalBytes / 1000) / (double)((dwCurrentTick - dwStartTick) / 1000);
pManager->m_ctrlDProgress.SetPos(dwTotalBytes);
sprintf(sMsg, "Read : [%09d / %09d]---[%4.2f KB/s]", dwTotalBytes, dwFileSize, fRate);
pManager->m_ctrlDStatus.SetWindowText(sMsg);
if(pManager->m_bCancel)
{
file.Close();
InternetCloseHandle(m_hHttpConnection);
InternetCloseHandle(m_hInternetSession);
::PostMessage(pManager->m_hWnd, WM_DOWNCANCEL, 0, 0);
return 0;
}
}
} while(dwRead != 0);
pManager->m_ctrlDProgress.SetPos(0);
file.Close();
InternetCloseHandle(m_hHttpConnection);
InternetCloseHandle(m_hInternetSession);
::PostMessage(pManager->m_hWnd, WM_DOWNCOMPLETE, 0, 0);
return 0;
}
HINTERNET hSession;
CString path;
////Win32 Internet functions 열기
hSession = InternetOpen("HTTP", INTERNET_OPEN_TYPE_DIRECT, NULL, NULL, 0);
if(hSession)
{
HINTERNET hService ;
hService = InternetOpenUrl(hSession, m_strFileURL, NULL, 0, 0, 0);
if(hService)
{
DWORD dwBytesAvailable, dwBytesRead;
/////InternetReadFile()함수를 사용하기 전에 읽어올 데이터의
////바이트 수를 읽어온다.
InternetQueryDataAvailable(hService, &dwBytesAvailable, 0, 0);
char *lpBuffer = (char *) malloc(dwBytesAvailable+1);
////웹 페이지의 소스 읽어오기
InternetReadFile(hService, lpBuffer, dwBytesAvailable, &dwBytesRead);
lpBuffer[dwBytesRead] = NULL;
TRY
{
TCHAR tempPath[MAX_PATH]= {0};
SHGetSpecialFolderPath(m_hWnd, tempPath, CSIDL_TEMPLATES, FALSE);
path = (CString)tempPath + "\\temp.doc";
char * pFileName;
pFileName = (char*)(LPCTSTR)path;
//앞에서 읽어온 소스를 "c:\\temp\\tmp.txt" 파일에 저장
CFile f(pFileName, CFile::modeCreate|CFile::modeWrite);
f.Write(lpBuffer, dwBytesRead);
f.Close();
}
CATCH(CFileException, e)
{
#ifdef _DEBUG
#endif
//e->GetErrorMessage(
}
END_CATCH
ShellExecute(m_hWnd, "open", path, NULL, NULL,SW_SHOWNORMAL);
free(lpBuffer);
}
}
InternetCloseHandle(hSession);
HINTERNET hINet, hConnection, hData;
CHAR buffer[2048] ;
CString m_strContents ;
DWORD dwRead, dwFlags, dwStatus ;
hINet = InternetOpen(
"InetURL/1.0", INTERNET_OPEN_TYPE_PRECONFIG, NULL, NULL, 0);
if (!hINet)
{
AfxMessageBox("InternetOpen Failed");
return;
}
try
{
hConnection = InternetConnect(
hINet, "www.somewhere.com", 80,
" "," ", INTERNET_SERVICE_HTTP, 0, 0);
if (!hConnection)
{
InternetCloseHandle(hINet);
return;
}
// Get data
hData = HttpOpenRequest(
hConnection, "GET", "/some_dir/somefile.html",
NULL, NULL, NULL, INTERNET_FLAG_KEEP_CONNECTION, 0);
if (!hData)
{
InternetCloseHandle(hConnection);
InternetCloseHandle(hINet);
return;
}
HttpSendRequest(hData, NULL, 0, NULL, 0);
while (InternetReadFile(hData, buffer, 255, &dwRead))
{
if (dwRead == 0) return;
buffer[dwRead] = 0;
m_strContents += buffer;
}
}
catch(CInternetException* e)
{
e->ReportError();
e->Delete();
}
InternetCloseHandle(hConnection);
InternetCloseHandle(hINet);
InternetCloseHandle(hData);// 파일다운로드
bool DownFile(LPCTSTR url,CString filename)
{
bool result=false;
try{
//http헤더 지정
char* headers="Accept:*/*\r\n"
"Accept-Language:zh-cn\r\n"
"User-Agent:VCTestClient\r\n";
// HINTERNET hNet = InternetOpen("Outlook",PRE_CONFIG_INTERNET_ACCESS,NULL,INTERNET_INVALID_PORT_NUMBER,0) ;
HINTERNET hNet = InternetOpen("FILEDOWN",PRE_CONFIG_INTERNET_ACCESS,NULL,NULL,0) ;
HINTERNET hUrlFile = InternetOpenUrl(hNet,url,headers,strlen(headers),INTERNET_FLAG_RELOAD,0);
char buffer[10*1024] ;
DWORD dwBytesRead = 1;
BOOL bRead=TRUE;
CFile file;
file.Open(filename,CFile::modeCreate|CFile::modeWrite);
while(bRead&&dwBytesRead>0)
{
bRead = InternetReadFile(hUrlFile,buffer,sizeof(buffer),&dwBytesRead);
if(dwBytesRead>0)
file.Write(buffer,dwBytesRead);
}
InternetCloseHandle(hUrlFile) ;
InternetCloseHandle(hNet) ;
file.Close();
result=true;
}catch(CException *e)
{
result=false;
}
return result;
}
//
// This is where all of the actually Internet work is done.
//
UINT CHTTPThread::DownloadRemoteFile()
{
UINT uiResult = HTTPTHREAD_FAILURE ;
char *pBuffer ;
HINTERNET hConnection ;
HINTERNET hHttpFile ;
BOOL bSendRequest ;
if (m_hSession == NULL)
{
//
// Call InternetOpen() to get a handle
// to an internet session.
//
m_hSession = ::InternetOpen(m_szTitle,
PRE_CONFIG_INTERNET_ACCESS,
NULL,
NULL,
0) ;
if (!m_hSession)
{
CHTTPThread::DebugMsg("InternetOpen() failed") ;
// Notify the thread manager that this thread failed...
if (m_pThreadMgr)
m_pThreadMgr->OnThreadComplete(m_iThreadNum,
m_szLocalFile, HTTPTHREAD_FAILURE) ;
return (HTTPTHREAD_FAILURE) ;
}
}
hConnection = ::InternetConnect(m_hSession,
m_strServer,
INTERNET_DEFAULT_HTTP_PORT,
"",
"",
INTERNET_SERVICE_HTTP,
0,
0) ;
if (hConnection == NULL)
{
CHTTPThread::DebugMsg("hConnection is NULL") ;
uiResult = HTTPTHREAD_COULDNOTCONNECT ;
}
if (hConnection != NULL)
{
hHttpFile = ::HttpOpenRequest(hConnection,
"GET",
m_strPath,
HTTP_VERSION,
"",
0,
INTERNET_FLAG_RELOAD,
0) ;
if (hHttpFile != NULL)
{
bSendRequest = ::HttpSendRequest(hHttpFile,
"",
0,
0,
0) ;
if (!bSendRequest)
{
CHTTPThread::DebugMsg("HttpSendRequest failed") ;
uiResult = HTTPTHREAD_FILENOTFOUND ;
}
else
{
// Get size of file.
char buffer[32] ;
DWORD dwFileSize ;
DWORD dwBufSize = sizeof(buffer) ;
BOOL bQuery ;
bQuery = ::HttpQueryInfo(hHttpFile,
HTTP_QUERY_CONTENT_LENGTH,
buffer,
&dwBufSize,
0) ;
if (bQuery)
{
// HttpQueryInfo was successful,
// so allocate the memory.
dwFileSize = (DWORD) atol(buffer) ;
}
else
{
// HttpQueryInfo failed, but allocate
// an 8K block anyway...
dwFileSize = 8192 ;
}
pBuffer = new char[dwFileSize + 1] ;
DWORD dwTotalBytes = dwFileSize + 1 ;
DWORD dwBytesRead ;
DWORD dwTotalBytesRead = 0 ;
dwTotalBytes = dwFileSize ;
BOOL bRead ;
bRead = ::InternetReadFile(hHttpFile,
pBuffer,
dwTotalBytes,
&dwBytesRead) ;
if (!bRead)
{
// InternetReadFile failed...
}
else
{
// Null-terminate the buffer
pBuffer[dwBytesRead] = 0 ;
uiResult = HTTPTHREAD_SUCCESS ;
// Save the data to the local file
if (strlen(m_szLocalFile))
{
CFile theFile ;
if (theFile.Open(m_szLocalFile,
CFile::modeCreate |
CFile::modeWrite))
{
theFile.Write(pBuffer, dwBytesRead) ;
theFile.Close() ;
}
else
{
uiResult = HTTPTHREAD_COULDNOTSAVEFILE ;
}
}
}
// free the buffer
delete [] pBuffer ;
}
::InternetCloseHandle(hHttpFile) ;
}
CHTTPThread::DebugMsg("closing connection...") ;
if (!::InternetCloseHandle(hConnection))
{
CHTTPThread::DebugMsg("InternetCloseHandle() failed") ;
}
}
// Notify the thread manager that this thread is complete...
if (m_pThreadMgr)
m_pThreadMgr->OnThreadComplete(m_iThreadNum,
m_szLocalFile, uiResult) ;
return (uiResult) ;
}
해당하는 컴퓨터가 인터넷에 연결되어있는지의 여부를 알려면 다음과 같이 하면 된다.
BOOL IsConnectInternet()
{
DWORD dwFlags;
BOOL bChkInternet = InternetGetConnectedState(&dwFlags,0);
if(!bChkInternet) return FALSE;
return TRUE;
}
.GetBindInfo()
.OnStartBinding()
.OnStopBinding()
.OnProgress()
S_OK
E_ABORT
ulProgress
ulProgressMax
ulStatusCode
BINDSTATUS_FINDINGRESOURCE
BINDSTATUS_CONNECTING
BINDSTATUS_SENDINGREQUEST
BINDSTATUS_MIMETYPEAVAILABLE
BINDSTATUS_BEGINDOWNLOADDATA
BINDSTATUS_ENDDOWNLOADDATA
BINDSTATUS_CACHEFILENAMEAVAILABLE
BINDSTATUS_DOWNLOADINGDATA
szStatusText
URLDownloadToFile()
URLDownloadToCacheFile()
combine the capabilities of asynchronous monikers and URL monikers into easy-to-use functions
do not have to worry about the protocols used to transfer the files, such as HTTP, FTP. In the simplest case, all you have to do is to pass them the URL
szURL // 다운받을 URL
szFileName // 내려받은 파일 이름
#ifndef __STATUSCALLBACK_H__
#define __STATUSCALLBACK_H__
#include <windows.h>
#include <urlmon.h>
#include <string>
//////////////////////////////////////////////////////////////////////////////
/// \class CCallback
/// \brief 인터넷 익스플로러를 이용해 HTTP로 파일을 다운로드받기 위한
/// COM 인터페이스 클래스.
//////////////////////////////////////////////////////////////////////////////
class CCallback : public IBindStatusCallback
{
private:
std::string m_URL; ///< 다운로드받을 파일의 URL
DWORD m_Timeout; ///< 타임아웃
public:
/// \brief 생성자
CCallback(const std::string& url, DWORD timeout=INFINITE);
/// \brief 소멸자
~CCallback();
public:
// IBindStatusCallback methods
STDMETHOD(OnStartBinding)(
/* [in] */ DWORD dwReserved,
/* [in] */ IBinding __RPC_FAR *pib)
{ return E_NOTIMPL; }
STDMETHOD(GetPriority)(
/* [out] */ LONG __RPC_FAR *pnPriority)
{ return E_NOTIMPL; }
STDMETHOD(OnLowResource)(
/* [in] */ DWORD reserved)
{ return E_NOTIMPL; }
STDMETHOD(OnProgress)(
/* [in] */ ULONG ulProgress,
/* [in] */ ULONG ulProgressMax,
/* [in] */ ULONG ulStatusCode,
/* [in] */ LPCWSTR wszStatusText);
STDMETHOD(OnStopBinding)(
/* [in] */ HRESULT hresult,
/* [unique][in] */ LPCWSTR szError)
{ return E_NOTIMPL; }
STDMETHOD(GetBindInfo)(
/* [out] */ DWORD __RPC_FAR *grfBINDF,
/* [unique][out][in] */ BINDINFO __RPC_FAR *pbindinfo)
{ return E_NOTIMPL; }
STDMETHOD(OnDataAvailable)(
/* [in] */ DWORD grfBSCF,
/* [in] */ DWORD dwSize,
/* [in] */ FORMATETC __RPC_FAR *pformatetc,
/* [in] */ STGMEDIUM __RPC_FAR *pstgmed)
{ return E_NOTIMPL; }
STDMETHOD(OnObjectAvailable)(
/* [in] */ REFIID riid,
/* [iid_is][in] */ IUnknown __RPC_FAR *punk)
{ return E_NOTIMPL; }
// IUnknown methods
STDMETHOD_(ULONG, AddRef)() { return 0; }
STDMETHOD_(ULONG, Release)() { return 0; }
STDMETHOD(QueryInterface)(
/* [in] */ REFIID riid,
/* [iid_is][out] */ void __RPC_FAR *__RPC_FAR *ppvObject)
{ return E_NOTIMPL; }
};
#endif //__BINDSTATUSCALLBACK_H__
#include "StatusCallback.h"
#include <shlwapi.h>
#include <mmsystem.h>
#include <iostream>
#include <assert.h>
//////////////////////////////////////////////////////////////////////////////
/// \brief 생성자
/// \param url 다운로드받을 파일의 URL
/// \param timeout 타임아웃
//////////////////////////////////////////////////////////////////////////////
CCallback::CCallback(const std::string& url, DWORD timeout)
: m_URL(url), m_Timeout(timeout)
{
assert(!m_URL.empty());
}
//////////////////////////////////////////////////////////////////////////////
/// \brief 소멸자
//////////////////////////////////////////////////////////////////////////////
CCallback::~CCallback()
{
}
//////////////////////////////////////////////////////////////////////////////
/// \brief 진행 상황을 알려주기 위해 인터넷 익스플로러가 호출하게 되는
/// 콜백 함수
///
/// \param ulProgress 다운로드받은 바이트 수
/// \param ulProgressMax 다운로드받아야할 전체 바이트 수
/// \param ulStatusCode 상태 코드
/// \param wszStatusText 상태 문자열
/// \return HRESULT 인터넷 익스플로러에게 알려줘야하는 결과값. 다운로드를
/// 계속해야하는 경우에는 S_OK를 반환해야하고, 중단하려면 E_ABORT를 반환해야
/// 한다.
//////////////////////////////////////////////////////////////////////////////
HRESULT STDMETHODCALLTYPE CCallback::OnProgress(ULONG ulProgress,
ULONG ulProgressMax,
ULONG ulStatusCode,
LPCWSTR wszStatusText)
{
// 이 함수 내부에서 혹시 사용자가 중지 버튼을 눌렀다던가,
// 타임아웃이 되었다던가, ulStatusCode가 이상하던가 하면,
// E_ABORT를 반환해서, 다운로드를 중단해야 한다.
if (m_Timeout < timeGetTime())
{
std::cout << "대기 시간이 초과되었습니다" << std::endl;
return E_ABORT;
}
// 다운로드를 중지해야하는 상황이 아니라면,
// ulProgress 값과, ulProgressMax 값을 이용해
// 프로그레스바 등을 적당히 업데이트하면 된다.
if (0 != ulProgressMax)
{
std::cout << "다운로드 중입니다 - " << m_URL
<< "(" << int( 100.0 * ulProgress / ulProgressMax) ) << "%)" << std::endl;
}
else
{
std::cout << "다운로드 중입니다 - " << m_URL << std::endl;
}
return S_OK;
}
string URL = "http://somewhere.com/something.zip";
string filename = "c:\something.zip";
CCallback callback(URL, timeGetTime() + 60 * 1000);
HRESULT hr = ::URLDownloadToFile(
NULL, URL.c_str(), filename.c_str(), 0, &callback);
비동기 모니커
URL 모니커IMoniker::CreateURLMoniker()
.BindToStorage()
참조 사이트:
http://support.microsoft.com/kb/149413
http://support.microsoft.com/kb/165298
http://support.microsoft.com/kb/184352/ko
http://serious-code.net/moin.cgi/WindowsInternetApi#head-f40b27d6b8b9a4fc3827264c1da16a04ecf4d094
http://serious-code.net/moin.cgi/RetrievingFileUsingHttp#head-b2d991512e63dd439c71dbb05763581360526535
http://cafe.naver.com/javacircle.cafe?iframe_url=/ArticleRead.nhn%3Farticleid=16330
http://blog.naver.com/kisatsg?Redirect=Log&logNo=20014263064
http://support.microsoft.com/kb/177188/ko
http://club.enclean.com/intro/board/view.form.do?msgId=28752&menuId=7&clbId=cclub
http://support.microsoft.com/default.aspx?scid=kb;en-us;224318
http://www.devpia.com/MAEUL/Contents/Detail.aspx?BoardID=51&MAEULNo=20&no=4502&ref=1518
http://www.codeproject.com/KB/IP/urldownload.aspx?display=Print
http://www.codeguru.com/cpp/i-n/internet/generalinternet/print.php/c3467/
http://support.microsoft.com/kb/165800/en-us/