⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 inet.cpp

📁 网络图片收集软件
💻 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 + -