📄 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
// 定义协议类型即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;
// 能够处理的数据类型,下面的定义表示能够处理所有的类型
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);//现在开始采用异步调用下载文件
// 是否成功
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]);
}
//现在如果要保存大的图片信息,因一次GetFile数据读不完需要在
//本函数中进行续读,要在本函数把信息保存起来。对于页面来说不用考虑这种情况
CInet::RESULTS CInet::SaveFile(CString &strFileName, BYTE *pbyBuffer, int nLen)
{
CFile fileOut;
CFileException ex;
CString strTempName=strFileName;
strTempName=strTempName.SpanExcluding("#");
//创建本地文件
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 应该为NULL,否则ptime应该为指向一个CTime对象的指针
//strURL应该为一个完整的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
{ //初始化返回的数据
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分钟
{//现在等待已经超时需要退出
::SetEvent(m_event[2]);//设置回调函数退出的信号
Sleep(1000);
return TIMEOUT;
}
}
}
//现在m_hFile可以使用了
dwStatusSize=sizeof(dwStatusCode);
if(FALSE==::HttpQueryInfo(m_hFile,HTTP_QUERY_STATUS_CODE|HTTP_QUERY_FLAG_NUMBER,&dwStatusCode,&dwStatusSize,NULL))
{//退出出现错误
}
// 需要重定向该页面
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;
//下面开始检查网页下载中是否图片
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;//文件的大小已经超出了缓存的大小
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)
{//现在网络已经慢的不能忍受了可以考虑退出了
return TIMEOUT;
}
}
}
if(m_pProgress->IsAborted())
return UNKNOWN_ERROR;
if(i_buf.dwBufferLength==0)//文件已经读完
{
ContentLenght=i;//ContentLenght中存放的是文件的真实大小
break;
}
i+=i_buf.dwBufferLength;
}
pbyTempBuffer[ContentLenght]='\0';// 以NULL结束缓冲区
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;
//句柄被关闭
case INTERNET_STATUS_HANDLE_CLOSING:
::SetEvent(pObj->m_event[1]);
break;
case INTERNET_STATUS_REQUEST_COMPLETE:
if(ERROR_SUCCESS==((LPINTERNET_ASYNC_RESULT)(lpvStatusInformation))->dwError)
{//设置句柄被创建事件或者读数据完成事件
::SetEvent(pObj->m_event[0]);
}
else
{//发生错误事件,则设置子线程退出事件,这里非常重要一定要处理
::SetEvent(pObj->m_event[2]);
}
break;
}
}
DWORD WINAPI CInet::AsyncCallbackThread(LPVOID lpParameter)
{
CInet * pObj=(CInet*)lpParameter;
::InternetSetStatusCallback(pObj->m_hSession,AsyncInternetCallback);
//通知子线程回调函数设置成功,子线程可以继续执行
::SetEvent(pObj->m_event[0]);
//等待文件下载完毕或者发生超时事件,如果发生了上面的事情则准备退出
::WaitForSingleObject(pObj->m_event[2],INFINITE);
return 0;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -