借鉴了网上的,忘记是在哪里看到的了。 增加了对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);