借鉴了网上的,忘记是在哪里看到的了。 增加了对HTTPS的支持。用到了MFC的CString,可以自行修改无需MFC。直接贴代码:
WebClient.h:
#pragma once #include <Windows.h> #include <winhttp.h> #pragma comment(lib, "Winhttp.lib") #include <vector> #ifdef _DLL #ifndef _AFXDLL #error 需要MFC支持! #endif #endif #ifndef _UNICODE #error 只能用于UNICODE项目中! #endif //小型动态缓冲区 //仅支持基本数据类型 template<typename T> class DynamicBuffer { enum { DEFAULT_SIZE = 32000, //默认初始大小 GROW_SIEZ = 32000, //每次增长大小 }; private: T *m_pData; size_t m_nData; size_t m_nBuffer; public: explicit DynamicBuffer(const T *pData = NULL, size_t nData = 0); //允许用右值构造 DynamicBuffer(const DynamicBuffer &&RValue); //允许用右值赋值 DynamicBuffer& operator = (const DynamicBuffer &&RValue); ~DynamicBuffer(); //追加数据 void Append(const T *pData, size_t nData); //清空所有数据,恢复默认构造后的状态 void Clear(); //释放所有内存,一般在不再使用时才调用 bool Release(); //获取保存的数据大小 size_t Size() { return m_nData; } const T* Data() { return m_pData; } operator const T*() { return m_pData; } private: DynamicBuffer(const DynamicBuffer&); DynamicBuffer& operator = (const DynamicBuffer&); }; class WebClient { public: enum RetCode { SUCCESS = 0, INVALID_URL = 1, WINHTTP_ERROR = 2, INTERNET_ERROR = 3, TIMEOUT_ERROR = 4, CREATE_FILE_ERROR = 5, }; enum { ANSI = 1, UTF8 = 2, }; private: HINTERNET m_hSession; CStringW m_strUserAgent; int m_CharSet; public: explicit WebClient(LPCWSTR wszUserAgent = L"Mozilla/5.0"); ~WebClient(); //清理Cookie,重置会话 void ClearAll(); //发起GET请求,获取页面HTML RetCode Get(LPCWSTR wszUrl, CStringW &strHtml,int iCnt = 0); RetCode GetEx(LPCWSTR wszUrl, const CStringW &strHead, CStringW &strHtml,int iCnt = 0); RetCode GetEx(LPCWSTR wszUrl, const std::vector<CStringW> &vec_strHead, CStringW &strHtml,int iCnt =0); //发起POST请求,获取返回的HTML RetCode Post(LPCWSTR wszUrl, const CStringW &strPostData, CStringW &strHtml); RetCode PostEx(LPCWSTR wszUrl, const CStringW &strPostData, const CStringW &strHead, CStringW &strHtml); RetCode PostEx(LPCWSTR wszUrl, const CStringW &strPostData, const std::vector<CStringW> &vec_strHead, CStringW &strHtml); //下载文件 RetCode DownloadFile(LPCWSTR wszUrl, LPCWSTR wszFilePath); //设置超时值 bool SetTimeouts(DWORD dwConnectTimeout, DWORD dwTransmissionTimeout); //设置代理 bool SetProxy(const CStringW &strProxy); //取消代理 bool RemoveProxy(); //设置目标网站编码,默认为UTF8 bool CharSet(int iCharSet); private: enum { MAX_URL_LENGTH = 2084, TEMP_BUFFER_SIZE = 4096,//4000, }; //分析URL bool ParseUrl(LPCWSTR wszUrl, int &iProtocol, WORD &nPort, CStringW &strHostName, CStringW &strUrlPath); //编码转换 CStringW UTF8ToUTF16(LPCSTR szUTF8, int nLen = -1); CStringW AnsiToUTF16(LPCSTR szAnsi, int nLen = -1); CStringA UTF16ToUTF8(LPCWSTR wszUTF16, int nLen = -1); private: WebClient(const WebClient&); WebClient& operator = (const WebClient&); };
WebClient.cpp:
#include "stdafx.h" #include "WebClient.h" #ifdef _DEBUG #define new DEBUG_NEW #endif //小型动态缓冲区 template<typename T> DynamicBuffer<T>::DynamicBuffer(const T *pData /*=NULL*/, size_t nData /*=0*/) { ASSERT(!(!pData && nData != 0)); if (nData > DEFAULT_SIZE) m_nBuffer = nData + GROW_SIEZ; else m_nBuffer = DEFAULT_SIZE; m_pData = (T*)malloc(m_nBuffer * sizeof(T)); memset(m_pData, 0, m_nBuffer * sizeof(T)); if (pData) memcpy_s(m_pData, m_nBuffer * sizeof(T), pData, nData * sizeof(T)); m_nData = nData; } //允许用右值构造 template<typename T> DynamicBuffer<T>::DynamicBuffer(const DynamicBuffer &&RValue) { m_pData = RValue.m_pData; m_nData = RValue.m_nData; m_nBuffer = RValue.m_nBuffer; } //允许用右值赋值 template<typename T> DynamicBuffer<T>& DynamicBuffer<T>::operator = (const DynamicBuffer &&RValue) { if (m_pData) free(m_pData); m_pData = RValue.m_pData; m_nData = RValue.m_nData; m_nBuffer = RValue.m_nBuffer; return *this; } template<typename T> DynamicBuffer<T>::~DynamicBuffer() { Release(); } //追加数据 template<typename T> void DynamicBuffer<T>::Append(const T *pData, size_t nData) { ASSERT(!(pData == NULL && nData != 0)); if (nData > m_nBuffer - m_nData) { //需要重新分配内存 size_t nNewBuffer = 0; if (nData > GROW_SIEZ) nNewBuffer = m_nData + nData + GROW_SIEZ; else nNewBuffer = m_nBuffer + GROW_SIEZ; m_pData = (T*)realloc(m_pData, nNewBuffer * sizeof(T)); memset(m_pData + m_nBuffer, 0, (nNewBuffer - m_nBuffer) * sizeof(T)); m_nBuffer = nNewBuffer; } memcpy_s(m_pData + m_nData, (m_nBuffer - m_nData) * sizeof(T), pData, nData * sizeof(T)); m_nData += nData; } //释放所有内存,一般在不再使用时才调用 template<typename T> bool DynamicBuffer<T>::Release() { if (m_pData) { free(m_pData); m_pData = NULL; m_nData = 0; m_nBuffer = 0; return true; } else return false; } //清空所有数据,恢复默认构造后的状态 template<typename T> void DynamicBuffer<T>::Clear() { if (m_pData && m_nBuffer == DEFAULT_SIZE) { //已经是默认构造后的大小,清空下数据即可 memset(m_pData, 0, m_nBuffer); m_nData = 0; return; } if (m_pData) free(m_pData); m_pData = (T*)malloc(DEFAULT_SIZE * sizeof(T)); memset(m_pData, 0, DEFAULT_SIZE * sizeof(T)); m_nBuffer = DEFAULT_SIZE; m_nData = 0; } WebClient::WebClient(LPCWSTR wszUserAgent /*= L"Mozilla/5.0"*/) { ASSERT(wszUserAgent != NULL); m_CharSet = UTF8; m_strUserAgent = wszUserAgent; m_hSession = WinHttpOpen(m_strUserAgent, WINHTTP_ACCESS_TYPE_NO_PROXY, WINHTTP_NO_PROXY_NAME, WINHTTP_NO_PROXY_BYPASS, NULL); //自动跟踪所有重定向 DWORD dwOption = WINHTTP_OPTION_REDIRECT_POLICY_ALWAYS; BOOL bSuccessSet = WinHttpSetOption(m_hSession, WINHTTP_OPTION_REDIRECT_POLICY, &dwOption, sizeof(DWORD)); ASSERT(m_hSession != NULL && bSuccessSet); } WebClient::~WebClient() { if (m_hSession) WinHttpCloseHandle(m_hSession); } //清理Cookie,重置会话 void WebClient::ClearAll() { if (m_hSession) WinHttpCloseHandle(m_hSession); m_hSession = WinHttpOpen(m_strUserAgent, WINHTTP_ACCESS_TYPE_NO_PROXY, WINHTTP_NO_PROXY_NAME, WINHTTP_NO_PROXY_BYPASS, NULL); //自动跟踪所有重定向 DWORD dwOption = WINHTTP_OPTION_REDIRECT_POLICY_ALWAYS; BOOL bSuccessSet = WinHttpSetOption(m_hSession, WINHTTP_OPTION_REDIRECT_POLICY, &dwOption, sizeof(DWORD)); ASSERT(m_hSession != NULL && bSuccessSet); } //发起GET请求,获取页面HTML WebClient::RetCode WebClient::Get(LPCWSTR wszUrl, CStringW &strHtml,int iCnt) { return GetEx(wszUrl, L"", strHtml,iCnt); } WebClient::RetCode WebClient::GetEx(LPCWSTR wszUrl, const CStringW &strHead, CStringW &strHtml,int iCnt) { std::vector<CStringW> vec_strHead; if (!strHead.IsEmpty()) vec_strHead.push_back(strHead); return GetEx(wszUrl, vec_strHead, strHtml,iCnt); } WebClient::RetCode WebClient::GetEx(LPCWSTR wszUrl, const std::vector<CStringW> &vec_strHead, CStringW &strHtml,int iCnt) { ASSERT(wszUrl != NULL); //解析URL int iProtocal; WORD nPort; CStringW strHostName, strUrlPath; if (!ParseUrl(wszUrl, iProtocal, nPort, strHostName, strUrlPath)) return INVALID_URL; HINTERNET hConnect = WinHttpConnect(m_hSession, strHostName, nPort, NULL); if (!hConnect) return WINHTTP_ERROR; //不接受缓存 DWORD dwFlags = WINHTTP_FLAG_REFRESH; if (iProtocal == INTERNET_SCHEME_HTTPS) { dwFlags |= WINHTTP_FLAG_SECURE; } HINTERNET hRequest = WinHttpOpenRequest(hConnect, L"GET", strUrlPath, NULL, WINHTTP_NO_REFERER, WINHTTP_DEFAULT_ACCEPT_TYPES, dwFlags); if (!hRequest) { WinHttpCloseHandle(hConnect); return WINHTTP_ERROR; } ////////////////////////////////////////////////////////////////////////// //添加请求头 FOR HTTPS DWORD dwBuffLen = sizeof(dwFlags); WinHttpQueryOption (hRequest, WINHTTP_OPTION_SECURITY_FLAGS, (LPVOID)&dwFlags, &dwBuffLen); dwFlags |= SECURITY_FLAG_IGNORE_UNKNOWN_CA; dwFlags |= SECURITY_FLAG_IGNORE_CERT_DATE_INVALID; dwFlags |= SECURITY_FLAG_IGNORE_CERT_CN_INVALID; // dwFlags |= SECURITY_FLAG_IGNORE_CERT_WRONG_USAGE; WinHttpSetOption (hRequest, WINHTTP_OPTION_SECURITY_FLAGS, &dwFlags, sizeof (dwFlags) ); ////////////////////end////////////////////////////////////////////////// for (size_t i=0; i<vec_strHead.size(); i++) { if (!vec_strHead[i].IsEmpty()) { WinHttpAddRequestHeaders(hRequest, vec_strHead[i], -1L, WINHTTP_ADDREQ_FLAG_ADD|WINHTTP_ADDREQ_FLAG_REPLACE); } } ////////////////////////////////////////////////////////////////////////// //发送请求 if (!WinHttpSendRequest(hRequest, WINHTTP_NO_ADDITIONAL_HEADERS, NULL, WINHTTP_NO_REQUEST_DATA, NULL, NULL, NULL)) { DWORD dwErrorCode = GetLastError(); RetCode retcode; if (dwErrorCode == ERROR_WINHTTP_NAME_NOT_RESOLVED || dwErrorCode == ERROR_WINHTTP_CANNOT_CONNECT || dwErrorCode == ERROR_WINHTTP_INVALID_SERVER_RESPONSE || dwErrorCode == ERROR_WINHTTP_CONNECTION_ERROR) retcode = INTERNET_ERROR; else if (dwErrorCode == ERROR_WINHTTP_TIMEOUT) retcode = TIMEOUT_ERROR; else retcode = WINHTTP_ERROR; WinHttpCloseHandle(hRequest); WinHttpCloseHandle(hConnect); return retcode; } //接收内容 if (!WinHttpReceiveResponse(hRequest, NULL)) { DWORD dwErrorCode = GetLastError(); RetCode retcode; if (dwErrorCode == ERROR_WINHTTP_NAME_NOT_RESOLVED || dwErrorCode == ERROR_WINHTTP_CANNOT_CONNECT || dwErrorCode == ERROR_WINHTTP_INVALID_SERVER_RESPONSE || dwErrorCode == ERROR_WINHTTP_CONNECTION_ERROR) retcode = INTERNET_ERROR; else if (dwErrorCode == ERROR_WINHTTP_TIMEOUT) retcode = TIMEOUT_ERROR; else retcode = WINHTTP_ERROR; WinHttpCloseHandle(hRequest); WinHttpCloseHandle(hConnect); return retcode; } //读出内容 DynamicBuffer<char> DyBuffData; char *pTempBuffer = new char[TEMP_BUFFER_SIZE]; DWORD dwRead = 0; //写入文件 FILE *fp; char name[64]; ZeroMemory(name,64); //这边我所请求的数据是已知的jpg图片 sprintf(name,"%d.jpg",iCnt); if ((fp = fopen(name, "ab+")) == NULL) // 存储图片 return CREATE_FILE_ERROR; do { memset(pTempBuffer, 0, TEMP_BUFFER_SIZE); if (!WinHttpReadData(hRequest, pTempBuffer, TEMP_BUFFER_SIZE, &dwRead)) { DWORD dwErrorCode = GetLastError(); RetCode retcode; if (dwErrorCode == ERROR_WINHTTP_NAME_NOT_RESOLVED || dwErrorCode == ERROR_WINHTTP_CANNOT_CONNECT || dwErrorCode == ERROR_WINHTTP_INVALID_SERVER_RESPONSE || dwErrorCode == ERROR_WINHTTP_CONNECTION_ERROR) retcode = INTERNET_ERROR; else if (dwErrorCode == ERROR_WINHTTP_TIMEOUT) retcode = TIMEOUT_ERROR; else retcode = WINHTTP_ERROR; delete [] pTempBuffer; WinHttpCloseHandle(hRequest); WinHttpCloseHandle(hConnect); return retcode; } dwRead > 0?fwrite(pTempBuffer, dwRead,1 ,fp):NULL; DyBuffData.Append(pTempBuffer, dwRead); } while (dwRead > 0); delete [] pTempBuffer; WinHttpCloseHandle(hRequest); WinHttpCloseHandle(hConnect); //关闭文件 fclose(fp); //进行编码转换 if (m_CharSet == UTF8) { strHtml = UTF8ToUTF16(DyBuffData, DyBuffData.Size()); } else { strHtml = AnsiToUTF16(DyBuffData, DyBuffData.Size()); } return SUCCESS; } //下载文件 WebClient::RetCode WebClient::DownloadFile(LPCWSTR wszUrl, LPCWSTR wszFilePath) { ASSERT(wszUrl != NULL && wszFilePath != NULL); //解析URL int iProtocal; WORD nPort; CStringW strHostName, strUrlPath; if (!ParseUrl(wszUrl, iProtocal, nPort, strHostName, strUrlPath)) return INVALID_URL; HINTERNET hConnect = WinHttpConnect(m_hSession, strHostName, nPort, NULL); if (!hConnect) return WINHTTP_ERROR; //不接受缓存 DWORD dwFlags = WINHTTP_FLAG_REFRESH; if (iProtocal == INTERNET_SCHEME_HTTPS) dwFlags |= WINHTTP_FLAG_SECURE; HINTERNET hRequest = WinHttpOpenRequest(hConnect, L"GET", strUrlPath, NULL, WINHTTP_NO_REFERER, WINHTTP_DEFAULT_ACCEPT_TYPES, dwFlags); if (!hRequest) { WinHttpCloseHandle(hConnect); return WINHTTP_ERROR; } //发送请求 if (!WinHttpSendRequest(hRequest, WINHTTP_NO_ADDITIONAL_HEADERS, NULL, WINHTTP_NO_REQUEST_DATA, NULL, NULL, NULL)) { DWORD dwErrorCode = GetLastError(); RetCode retcode; if (dwErrorCode == ERROR_WINHTTP_NAME_NOT_RESOLVED || dwErrorCode == ERROR_WINHTTP_CANNOT_CONNECT || dwErrorCode == ERROR_WINHTTP_INVALID_SERVER_RESPONSE || dwErrorCode == ERROR_WINHTTP_CONNECTION_ERROR) retcode = INTERNET_ERROR; else if (dwErrorCode == ERROR_WINHTTP_TIMEOUT) retcode = TIMEOUT_ERROR; else retcode = WINHTTP_ERROR; WinHttpCloseHandle(hRequest); WinHttpCloseHandle(hConnect); return retcode; } //接收内容 if (!WinHttpReceiveResponse(hRequest, NULL)) { DWORD dwErrorCode = GetLastError(); RetCode retcode; if (dwErrorCode == ERROR_WINHTTP_NAME_NOT_RESOLVED || dwErrorCode == ERROR_WINHTTP_CANNOT_CONNECT || dwErrorCode == ERROR_WINHTTP_INVALID_SERVER_RESPONSE || dwErrorCode == ERROR_WINHTTP_CONNECTION_ERROR) retcode = INTERNET_ERROR; else if (dwErrorCode == ERROR_WINHTTP_TIMEOUT) retcode = TIMEOUT_ERROR; else retcode = WINHTTP_ERROR; WinHttpCloseHandle(hRequest); WinHttpCloseHandle(hConnect); return retcode; } //读出内容,写入到文件 CFile File; if (!File.Open(wszFilePath, CFile::modeCreate|CFile::modeWrite|CFile::shareDenyWrite)) { WinHttpCloseHandle(hRequest); WinHttpCloseHandle(hConnect); return CREATE_FILE_ERROR; } char *pTempBuffer = new char[TEMP_BUFFER_SIZE]; DWORD dwRead = 0; do { memset(pTempBuffer, 0, TEMP_BUFFER_SIZE); if (!WinHttpReadData(hRequest, pTempBuffer, TEMP_BUFFER_SIZE, &dwRead)) { DWORD dwErrorCode = GetLastError(); RetCode retcode; if (dwErrorCode == ERROR_WINHTTP_NAME_NOT_RESOLVED || dwErrorCode == ERROR_WINHTTP_CANNOT_CONNECT || dwErrorCode == ERROR_WINHTTP_INVALID_SERVER_RESPONSE || dwErrorCode == ERROR_WINHTTP_CONNECTION_ERROR) retcode = INTERNET_ERROR; else if (dwErrorCode == ERROR_WINHTTP_TIMEOUT) retcode = TIMEOUT_ERROR; else retcode = WINHTTP_ERROR; delete [] pTempBuffer; WinHttpCloseHandle(hRequest); WinHttpCloseHandle(hConnect); //未下载完,网络异常,删除文件 File.Close(); ::DeleteFileW(wszFilePath); return retcode; } File.Write(pTempBuffer, dwRead); } while (dwRead > 0); delete [] pTempBuffer; WinHttpCloseHandle(hRequest); WinHttpCloseHandle(hConnect); File.Close(); return SUCCESS; } //发起POST请求,获取返回的HTML WebClient::RetCode WebClient::Post(LPCWSTR wszUrl, const CStringW &strPostData, CStringW &strHtml) { return PostEx(wszUrl, strPostData, L"", strHtml); } WebClient::RetCode WebClient::PostEx(LPCWSTR wszUrl, const CStringW &strPostData, const CStringW &strHead, CStringW &strHtml) { std::vector<CStringW> vec_strHead; if (!strHead.IsEmpty()) vec_strHead.push_back(strHead); return PostEx(wszUrl, strPostData, vec_strHead, strHtml); } WebClient::RetCode WebClient::PostEx(LPCWSTR wszUrl, const CStringW &strPostData, const std::vector<CStringW> &vec_strHead, CStringW &strHtml) { ASSERT(wszUrl != NULL); //解析URL int iProtocal; WORD nPort; CStringW strHostName, strUrlPath; if (!ParseUrl(wszUrl, iProtocal, nPort, strHostName, strUrlPath)) return INVALID_URL; HINTERNET hConnect = WinHttpConnect(m_hSession, strHostName, nPort, NULL); if (!hConnect) return WINHTTP_ERROR; //不接受缓存 DWORD dwFlags = WINHTTP_FLAG_REFRESH; if (iProtocal == INTERNET_SCHEME_HTTPS) dwFlags |= WINHTTP_FLAG_SECURE; HINTERNET hRequest = WinHttpOpenRequest(hConnect, L"POST", strUrlPath, NULL, WINHTTP_NO_REFERER, WINHTTP_DEFAULT_ACCEPT_TYPES, dwFlags); if (!hRequest) { WinHttpCloseHandle(hConnect); return WINHTTP_ERROR; } //添加POST必备的请求头 WinHttpAddRequestHeaders(hRequest, L"Content-Type: application/x-www-form-urlencoded", -1L, WINHTTP_ADDREQ_FLAG_ADD|WINHTTP_ADDREQ_FLAG_REPLACE); //添加其它请求头 for (size_t i=0; i<vec_strHead.size(); i++) { if (!vec_strHead[i].IsEmpty()) { WinHttpAddRequestHeaders(hRequest, vec_strHead[i], -1L, WINHTTP_ADDREQ_FLAG_ADD|WINHTTP_ADDREQ_FLAG_REPLACE); } } //转换编码 CStringA strPostData_utf8 = UTF16ToUTF8(strPostData); //发送请求 if (!WinHttpSendRequest(hRequest, WINHTTP_NO_ADDITIONAL_HEADERS, NULL, (LPSTR)(LPCSTR)strPostData_utf8, strPostData_utf8.GetLength(), strPostData_utf8.GetLength(), NULL)) { DWORD dwErrorCode = GetLastError(); RetCode retcode; if (dwErrorCode == ERROR_WINHTTP_NAME_NOT_RESOLVED || dwErrorCode == ERROR_WINHTTP_CANNOT_CONNECT || dwErrorCode == ERROR_WINHTTP_INVALID_SERVER_RESPONSE || dwErrorCode == ERROR_WINHTTP_CONNECTION_ERROR) retcode = INTERNET_ERROR; else if (dwErrorCode == ERROR_WINHTTP_TIMEOUT) retcode = TIMEOUT_ERROR; else retcode = WINHTTP_ERROR; WinHttpCloseHandle(hRequest); WinHttpCloseHandle(hConnect); return retcode; } //接收内容 if (!WinHttpReceiveResponse(hRequest, NULL)) { DWORD dwErrorCode = GetLastError(); RetCode retcode; if (dwErrorCode == ERROR_WINHTTP_NAME_NOT_RESOLVED || dwErrorCode == ERROR_WINHTTP_CANNOT_CONNECT || dwErrorCode == ERROR_WINHTTP_INVALID_SERVER_RESPONSE || dwErrorCode == ERROR_WINHTTP_CONNECTION_ERROR) retcode = INTERNET_ERROR; else if (dwErrorCode == ERROR_WINHTTP_TIMEOUT) retcode = TIMEOUT_ERROR; else retcode = WINHTTP_ERROR; WinHttpCloseHandle(hRequest); WinHttpCloseHandle(hConnect); return retcode; } //读出内容 DynamicBuffer<char> DyBuffData; char *pTempBuffer = new char[TEMP_BUFFER_SIZE]; DWORD dwRead = 0; do { memset(pTempBuffer, 0, TEMP_BUFFER_SIZE); if (!WinHttpReadData(hRequest, pTempBuffer, TEMP_BUFFER_SIZE, &dwRead)) { DWORD dwErrorCode = GetLastError(); RetCode retcode; if (dwErrorCode == ERROR_WINHTTP_NAME_NOT_RESOLVED || dwErrorCode == ERROR_WINHTTP_CANNOT_CONNECT || dwErrorCode == ERROR_WINHTTP_INVALID_SERVER_RESPONSE || dwErrorCode == ERROR_WINHTTP_CONNECTION_ERROR) retcode = INTERNET_ERROR; else if (dwErrorCode == ERROR_WINHTTP_TIMEOUT) retcode = TIMEOUT_ERROR; else retcode = WINHTTP_ERROR; delete [] pTempBuffer; WinHttpCloseHandle(hRequest); WinHttpCloseHandle(hConnect); return retcode; } DyBuffData.Append(pTempBuffer, dwRead); } while (dwRead > 0); delete [] pTempBuffer; WinHttpCloseHandle(hRequest); WinHttpCloseHandle(hConnect); //进行编码转换 if (m_CharSet == UTF8) strHtml = UTF8ToUTF16(DyBuffData, DyBuffData.Size()); else strHtml = AnsiToUTF16(DyBuffData, DyBuffData.Size()); return SUCCESS; } //分析URL bool WebClient::ParseUrl(LPCWSTR wszUrl, int &iProtocol, WORD &nPort, CStringW &strHostName, CStringW &strUrlPath) { ASSERT(wszUrl != NULL); WCHAR *wszHostName = new WCHAR[MAX_URL_LENGTH+1]; WCHAR *wszUrlPath = new WCHAR[MAX_URL_LENGTH+1]; memset(wszHostName, 0 , MAX_URL_LENGTH+1); memset(wszUrlPath, 0, MAX_URL_LENGTH+1); URL_COMPONENTS urlComp = {sizeof(URL_COMPONENTS)}; urlComp.lpszHostName = wszHostName; urlComp.dwHostNameLength = MAX_URL_LENGTH; urlComp.lpszUrlPath = wszUrlPath; urlComp.dwUrlPathLength = MAX_URL_LENGTH; BOOL bSuccessParse = WinHttpCrackUrl(wszUrl, NULL, NULL, &urlComp); if (bSuccessParse) { iProtocol = urlComp.nScheme; nPort = urlComp.nPort; strHostName = urlComp.lpszHostName; strUrlPath = urlComp.lpszUrlPath; } delete [] wszHostName; delete [] wszUrlPath; if (bSuccessParse) return true; else return false; } //编码转换 CStringW WebClient::UTF8ToUTF16(LPCSTR szUTF8, int nLen /*= -1*/) { //先获取转换后需要的缓冲区大小 DWORD nWszLen = MultiByteToWideChar(CP_UTF8, NULL, szUTF8, nLen, NULL, NULL); CStringW strUTF16; nWszLen = MultiByteToWideChar(CP_UTF8, NULL, szUTF8, nLen, strUTF16.GetBuffer(nWszLen), nWszLen); strUTF16.ReleaseBuffer(nWszLen); return strUTF16; } CStringW WebClient::AnsiToUTF16(LPCSTR szAnsi, int nLen /*= -1*/) { //先获取转换后需要的缓冲区大小 DWORD nWszLen = MultiByteToWideChar(CP_ACP, NULL, szAnsi, nLen, NULL, NULL); CStringW strUTF16; nWszLen = MultiByteToWideChar(CP_ACP, NULL, szAnsi, nLen, strUTF16.GetBuffer(nWszLen), nWszLen); strUTF16.ReleaseBuffer(nWszLen); return strUTF16; } CStringA WebClient::UTF16ToUTF8(LPCWSTR wszUTF16, int nLen /*= -1*/) { //先获取转换后需要的缓冲区大小 DWORD nszLen = WideCharToMultiByte(CP_UTF8, NULL, wszUTF16, nLen, NULL, NULL, NULL, NULL); CStringA strUTF8; nszLen = WideCharToMultiByte(CP_UTF8, NULL, wszUTF16, nLen, strUTF8.GetBuffer(nszLen), nszLen, NULL, NULL); strUTF8.ReleaseBuffer(nszLen); return strUTF8; } //设置超时值 bool WebClient::SetTimeouts(DWORD dwConnectTimeout, DWORD dwTransmissionTimeout) { if (WinHttpSetTimeouts(m_hSession, 0, dwConnectTimeout, dwTransmissionTimeout, dwTransmissionTimeout)) return true; else return false; } //设置代理 bool WebClient::SetProxy(const CStringW &strProxy) { WINHTTP_PROXY_INFO ProxyInfo = {WINHTTP_ACCESS_TYPE_NAMED_PROXY, (LPWSTR)(LPCWSTR)strProxy, (LPWSTR)(LPCWSTR)strProxy}; if (WinHttpSetOption(m_hSession, WINHTTP_OPTION_PROXY, &ProxyInfo, sizeof(WINHTTP_PROXY_INFO))) return true; else return false; } //取消代理 bool WebClient::RemoveProxy() { WINHTTP_PROXY_INFO ProxyInfo = {WINHTTP_ACCESS_TYPE_NO_PROXY, NULL, NULL}; if (WinHttpSetOption(m_hSession, WINHTTP_OPTION_PROXY, &ProxyInfo, sizeof(WINHTTP_PROXY_INFO))) return true; else return false; } //设置目标网站编码 bool WebClient::CharSet(int iCharSet) { if (iCharSet != ANSI && iCharSet != UTF8) return false; m_CharSet = iCharSet; return true; }
调用:
WebClient webclient; g_iCnt = 0; CString strHtml; //请求12306的图片为例 webclient.Get(_T("https://kyfw.12306.cn/otn/passcodeNew/getPassCodeNew?module=login&rand=sjrand&0.7099142521619793"), strHtml,g_iCnt);