?? inet.cpp
字號:
// Inet.cpp: implementation of the CInet class.
//
//////////////////////////////////////////////////////////////////////
#include "stdafx.h"
#include "image.h"
#include "Inet.h"
//#include <direct.h>
//#include <process.h>
//#include <io.h>
#ifdef _DEBUG
#undef THIS_FILE
static char THIS_FILE[]=__FILE__;
#define new DEBUG_NEW
#endif
// 定義協(xié)議類型即HTTP類型
//static const char *szHttp = "http://";
// Request flags for session initialization:
// Use existing INET setup, don't redirect to other servers automatically,
// don't save pages in the browser's cache, always reload a page from the
// server (don't use the browser's cached copy)
static DWORD dwHttpRequestFlags =
INTERNET_FLAG_EXISTING_CONNECT|
INTERNET_FLAG_NO_AUTO_REDIRECT|
INTERNET_FLAG_DONT_CACHE|
INTERNET_FLAG_RELOAD;
// 能夠處理的數(shù)據(jù)類型,下面的定義表示能夠處理所有的類型
static const TCHAR szHeaders[] =
_T("Accept: */*\r\n");
//_T("*/*\r");
static const TCHAR szHeaders1[]=
_T("If-Modified-Since: ");
static const TCHAR szHeaders2[]=
_T("Connection: Keep-Alive\r");
static const TCHAR szHeaders3[]=
_T("Cookie: \r");
static const TCHAR szHeaders4[]=
_T("Accept-Language: zh-cn \r");
//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////
CInet::CInet()
{
m_hSession=NULL;
//m_minsize=10;
}
CInet::~CInet()
{
}
CInet::RESULTS CInet::OpenSession(BOOL bUseProxy, CString &strProxyName)
{
CInet::RESULTS ret;
m_hSession = ::InternetOpen("image",
bUseProxy?INTERNET_OPEN_TYPE_PROXY:INTERNET_OPEN_TYPE_PRECONFIG,
bUseProxy?(LPCTSTR)strProxyName:(LPCTSTR)NULL,
NULL,INTERNET_FLAG_ASYNC);//現(xiàn)在開始采用異步調(diào)用下載文件
// 是否成功
if(m_hSession != NULL)
{
DWORD dwTimeout = 8000;
::InternetSetOption(m_hSession,INTERNET_OPTION_CONNECT_TIMEOUT,
&dwTimeout,sizeof(dwTimeout));
ret = SUCCESS;
}
else ret = BAD_URL;
for(int i=0;i<3;i++)
m_event[i]=CreateEvent(NULL,FALSE,FALSE,NULL);
return(ret);
}
void CInet::CloseSession()
{
::InternetCloseHandle(m_hSession);
for(int i=0;i<3;i++)
CloseHandle(m_event[i]);
}
//現(xiàn)在如果要保存大的圖片信息,因一次GetFile數(shù)據(jù)讀不完需要在
//本函數(shù)中進行續(xù)讀,要在本函數(shù)把信息保存起來。對于頁面來說不用考慮這種情況
CInet::RESULTS CInet::SaveFile(CString &strFileName, BYTE *pbyBuffer, int nLen)
{
CFile fileOut;
CFileException ex;
CString strTempName=strFileName;
strTempName=strTempName.SpanExcluding("#");
//創(chuàng)建本地文件
if(fileOut.Open(strTempName,CFile::modeCreate|CFile::modeWrite,&ex))//CFile::modeNoTruncate
{
//fileOut.Seek(
fileOut.Write(pbyBuffer,nLen);
fileOut.Close();
}
else
return (BAD_FILENAME);
return (SUCCESS);
//return (UNKNOWN_ERROR);
}
//說明如果下載的為頁面 ptime 應(yīng)該為NULL,否則ptime應(yīng)該為指向一個CTime對象的指針
//strURL應(yīng)該為一個完整的url
CInet::RESULTS CInet::DoGet(CString &strURL, BYTE **pbyBuffer, int &nLen, CTime* ptime,bool bpage)
{
CInet::RESULTS nRetCode = UNKNOWN_ERROR;
CString strTempURL = strURL;
DWORD dwCallbackThreadID;
char szTemp[256];
CString t;
DWORD dwStatusCode;
DWORD dwStatusSize;
try
{ //初始化返回的數(shù)據(jù)
nLen=0;
CString strServer,strObject,strUser,strPassword;
INTERNET_PORT nPort;
DWORD dwServiceType;
if(!AfxParseURLEx(strTempURL,dwServiceType,strServer,strObject,nPort,strUser,strPassword,ICU_NO_ENCODE))
return(CInet::BAD_URL);
::ResetEvent(m_event[0]);
::CreateThread(NULL,0,AsyncCallbackThread,this,NULL,&dwCallbackThreadID);
::WaitForSingleObject(m_event[0],INFINITE);
//t=CTime::GetCurrentTime().FormatGmt("%a, %d %b %Y %I:%M:%S GMT");
//t=_T("If-Modified-Since: ")+t+"\r";
t=_T("Accept: */*\r\n");
//t=t+_T("Connection: Keep-Alive\r");
::ResetEvent(m_event[0]);
if(ptime!=NULL)
{
t=ptime->FormatGmt("%a, %d %b %Y %I:%M:%S GMT");
t=_T("If-Modified-Since: ")+t+"\r";
m_hFile=::InternetOpenUrl(m_hSession,strURL,t,t.GetLength(),INTERNET_FLAG_DONT_CACHE|INTERNET_FLAG_RELOAD,(DWORD)this);
}
else
m_hFile=::InternetOpenUrl(m_hSession,strURL,t,t.GetLength(),INTERNET_FLAG_DONT_CACHE|INTERNET_FLAG_RELOAD,(DWORD)this);
if(NULL==m_hFile)
{
if(ERROR_IO_PENDING==::GetLastError())
{
if(::WaitForSingleObject(m_event[0],1000*60*5)==WAIT_TIMEOUT)//等待5分鐘
{//現(xiàn)在等待已經(jīng)超時需要退出
::SetEvent(m_event[2]);//設(shè)置回調(diào)函數(shù)退出的信號
Sleep(1000);
return TIMEOUT;
}
}
}
//現(xiàn)在m_hFile可以使用了
dwStatusSize=sizeof(dwStatusCode);
if(FALSE==::HttpQueryInfo(m_hFile,HTTP_QUERY_STATUS_CODE|HTTP_QUERY_FLAG_NUMBER,&dwStatusCode,&dwStatusSize,NULL))
{//退出出現(xiàn)錯誤
}
// 需要重定向該頁面
if(dwStatusCode==HTTP_STATUS_MOVED||dwStatusCode==HTTP_STATUS_REDIRECT||dwStatusCode==HTTP_STATUS_REDIRECT_METHOD)
{
::HttpQueryInfo(m_hFile,HTTP_QUERY_LOCATION,NULL,&dwStatusSize,0);
::HttpQueryInfo(m_hFile,HTTP_QUERY_LOCATION,strTempURL.GetBufferSetLength(dwStatusSize),&dwStatusSize,0);
strTempURL.ReleaseBuffer(dwStatusSize);
CString strNewServer,strnewObject;
AfxParseURLEx(strTempURL,dwServiceType,strNewServer,strnewObject,nPort,strUser,strPassword,ICU_NO_ENCODE);
if(strNewServer.IsEmpty())
{
if(strTempURL.Left(1)!="/")
{
int i;
i=strObject.ReverseFind('/');
if(i!=-1)
strObject=strObject.Left(i);
else
strObject="";
if(strObject!="")
strTempURL=strObject+"/"+strTempURL;
else
strTempURL="/"+strTempURL;
}
strURL=strServer+strTempURL;
}else
strURL=strTempURL;
::InternetCloseHandle(m_hFile);
return(LOCATION_MOVED);
}
else if(dwStatusCode == HTTP_STATUS_REQUEST_TIMEOUT||dwStatusCode == HTTP_STATUS_GATEWAY_TIMEOUT||dwStatusCode== HTTP_STATUS_NOT_FOUND)
{
Sleep(500L);
::InternetCloseHandle(m_hFile);
return(TIMEOUT);
}
else if(dwStatusCode == HTTP_STATUS_OK)
{
BYTE *pbyTempBuffer = *pbyBuffer;
int hasRead=0;
BOOL bOkay = TRUE;
BOOL bImage=FALSE;
DWORD ContentLenght=0;
//下面開始檢查網(wǎng)頁下載中是否圖片
dwStatusSize=sizeof(ContentLenght);
if(!::HttpQueryInfo(m_hFile,HTTP_QUERY_CONTENT_LENGTH|HTTP_QUERY_FLAG_NUMBER,&ContentLenght,&dwStatusSize,NULL))
{
ContentLenght=MAX_INET_BUFFER;
}
if(ContentLenght>MAX_INET_BUFFER)
return nRetCode;//文件的大小已經(jīng)超出了緩存的大小
if(bpage)
{
dwStatusSize = sizeof(szTemp);
::HttpQueryInfo(m_hFile,HTTP_QUERY_CONTENT_TYPE,szTemp,&dwStatusSize,NULL);
CString type(szTemp);
type.MakeLower();
if(type.Left(5)=="image")
bImage=TRUE;
}
if(!bpage||bImage)
{
if(t<m_minsize*1000)
{
::InternetCloseHandle(m_hFile);
return (UNKNOWN_ERROR);
}
}
for(DWORD i=0;i<ContentLenght;)
{
INTERNET_BUFFERS i_buf={0};
i_buf.dwStructSize=sizeof(INTERNET_BUFFERS);
i_buf.lpvBuffer=pbyTempBuffer+i;
i_buf.dwBufferLength=1024*2;//2k的大小
::ResetEvent(m_event[0]);
if(::InternetReadFileEx(m_hFile,&i_buf,IRF_ASYNC,(DWORD)this)==FALSE)
{
if(ERROR_IO_PENDING==::GetLastError())
{
if(::WaitForSingleObject(m_event[0],5*60*1000)==WAIT_TIMEOUT)
{//現(xiàn)在網(wǎng)絡(luò)已經(jīng)慢的不能忍受了可以考慮退出了
return TIMEOUT;
}
}
}
if(m_pProgress->IsAborted())
return UNKNOWN_ERROR;
if(i_buf.dwBufferLength==0)//文件已經(jīng)讀完
{
ContentLenght=i;//ContentLenght中存放的是文件的真實大小
break;
}
i+=i_buf.dwBufferLength;
}
pbyTempBuffer[ContentLenght]='\0';// 以NULL結(jié)束緩沖區(qū)
nLen=ContentLenght;
::InternetCloseHandle(m_hFile);
if(bpage&&bImage)
return IMAGE_TYPE;
return(SUCCESS);
}
else
{
::InternetCloseHandle(m_hFile);
}
}
catch (...)
{
if(m_hFile)
::InternetCloseHandle(m_hFile);
return(UNKNOWN_ERROR);
}
return (UNKNOWN_ERROR);
}
CInet::RESULTS CInet::GetPage(CString &strURL, BYTE **pbyBuffer, int &nLen, BOOL bRedirectOkay)
{
int nRetries=2;
CInet::RESULTS ret;
do
{
//Get the page
ret=DoGet(strURL,pbyBuffer,nLen,NULL,true);
}
while(nRetries--&&((ret==LOCATION_MOVED && bRedirectOkay)|| ret==TIMEOUT));
return(ret);
}
CString CInet::SplitFileName(LPCTSTR lpszPath, int nSplit)
{
CString strResult;
char szPath[800],szDrive[800],szFileName[800],szExt[800];
_splitpath(lpszPath,szDrive,szPath,szFileName,szExt);
if(nSplit & CInet::DRIVE)
strResult += szDrive;
if(nSplit & CInet::PATH)
strResult += szPath;
if(nSplit & CInet::FNAME)
strResult += szFileName;
if(nSplit & CInet::EXT)
strResult += szExt;
return(strResult);
}
CString CInet::GetErrorText()
{
CString strError;
switch(m_dwRet)
{
case HTTP_STATUS_MOVED:
case HTTP_STATUS_REDIRECT:
case HTTP_STATUS_REDIRECT_METHOD:
strError = "Redirected, but not found";
break;
case HTTP_STATUS_REQUEST_TIMEOUT:
case HTTP_STATUS_GATEWAY_TIMEOUT:
strError = "Timed out on request";
break;
case HTTP_STATUS_NOT_FOUND:
case HTTP_STATUS_BAD_REQUEST:
case HTTP_STATUS_GONE:
strError = "Page or file not found";
break;
case HTTP_STATUS_DENIED:
case HTTP_STATUS_PAYMENT_REQ:
case HTTP_STATUS_FORBIDDEN:
//case HTTP_STATUS_AUTH_REFUSED:
// strError = "Access denied";
// break;
case HTTP_STATUS_PROXY_AUTH_REQ:
strError = "Proxy authentication required";
break;
default:
strError.Format("WinInet error %d",m_dwRet);
break;
}
return(strError);
}
CInet::RESULTS CInet::GetFile(CString &strURL, BYTE **pbyBuffer, int &nLen, CTime *ptime)
{
int nRetries=2;
CInet::RESULTS ret;
do
{
//Get the file
ret=DoGet(strURL,pbyBuffer,nLen,ptime,false);
}
while(nRetries--&&(ret==LOCATION_MOVED ||ret==TIMEOUT));
return (ret);
}
void CALLBACK CInet::AsyncInternetCallback(HINTERNET hInternet, DWORD dwContext, DWORD dwInternetStatus, LPVOID lpvStatusInformation, DWORD dwStatusINformationLength)
{
CInet *pObj=(CInet*)dwContext;
switch(dwInternetStatus)
{
case INTERNET_STATUS_HANDLE_CREATED:
pObj->m_hFile=(HINTERNET)(((LPINTERNET_ASYNC_RESULT)(lpvStatusInformation))->dwResult);
break;
//句柄被關(guān)閉
case INTERNET_STATUS_HANDLE_CLOSING:
::SetEvent(pObj->m_event[1]);
break;
case INTERNET_STATUS_REQUEST_COMPLETE:
if(ERROR_SUCCESS==((LPINTERNET_ASYNC_RESULT)(lpvStatusInformation))->dwError)
{//設(shè)置句柄被創(chuàng)建事件或者讀數(shù)據(jù)完成事件
::SetEvent(pObj->m_event[0]);
}
else
{//發(fā)生錯誤事件,則設(shè)置子線程退出事件,這里非常重要一定要處理
::SetEvent(pObj->m_event[2]);
}
break;
}
}
DWORD WINAPI CInet::AsyncCallbackThread(LPVOID lpParameter)
{
CInet * pObj=(CInet*)lpParameter;
::InternetSetStatusCallback(pObj->m_hSession,AsyncInternetCallback);
//通知子線程回調(diào)函數(shù)設(shè)置成功,子線程可以繼續(xù)執(zhí)行
::SetEvent(pObj->m_event[0]);
//等待文件下載完畢或者發(fā)生超時事件,如果發(fā)生了上面的事情則準備退出
::WaitForSingleObject(pObj->m_event[2],INFINITE);
return 0;
}
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -