http post的资料网上一大把, 不过用起来都是函数级别的, 不好用.
今天整理了一个类, 用于执行http post的操作, 使用起来方便多了.
调用端代码
// testHttpPost.cpp : Defines the entry point for the console application.
//
#include "stdafx.h"
#include "httpPost.h"
void fnTest();
int _tmain(int argc, _TCHAR* argv[])
{
fnTest();
_tprintf(L"END, press any key to quit\r\n");
getwchar();
return 0;
}
void fnTest()
{
BOOL bRc = FALSE;
std::string strRc = "";
std::string strTempA = "";
std::wstring strTemp = L"";
CHttpPost httpPost;
// 一个假设的url, 实际用的时候,搞一个能 post data 的url
bRc = httpPost.PostDataToWebA(
"http://www.baidu.com/s?rsv_bp=0&tn=baidu&rsv_spt=3&ie=utf-8&rsv_sug3=3&rsv_sug4=56&rsv_sug1=3&rsv_sug2=0&inputT=1755",
"&wd=中文",
strRc);
// real post format test ok
// bRc = httpPost.PostDataToWebA(
// "http://www.test.com/home.php?a=a1111&b=b2222",
// "NameList=name1,name2,name3",
// strRc);
strTemp = httpPost.StringFormatV(L"bRc = %s\r\n", bRc ? L"TRUE" : L"FALSE");
_tprintf(strTemp.c_str());
if (bRc)
{
strRc = httpPost.Utf82ansi(strRc); ///< 网页返回来的是utf8
strTempA = httpPost.StringFormatVA("strRc = %s\r\n", strRc.c_str());
printf(strTempA.c_str());
}
}
封装类实现
/// @file httpPost.h
/// @brief 封装httpPost的操作
#ifndef __HTTP_POST_H__
#define __HTTP_POST_H__
#include <windows.h>
#include <tchar.h>
#include <string>
#include <wininet.h>
#pragma comment(lib, "wininet.lib")
#include <atlconv.h>
#include <UrlMon.h>
#pragma comment(lib, "urlmon.lib")
#include <shlwapi.h>
#pragma comment(lib, "shlwapi.lib")
#ifndef SAFE_DELETE_ARRAY
#define SAFE_DELETE_ARRAY(p) \
if (NULL != (p)) \
{ \
delete [](p); \
(p) = NULL; \
}
#endif
class CHttpPost
{
public:
CHttpPost();
virtual ~CHttpPost();
BOOL PostDataToWebA(
const char* pcUrl,
const char* pcDataToPostA,
std::string& strDataReturnFromWeb);
// Utility
std::wstring StringFormatV(WCHAR * szFormat, ...);
std::string StringFormatVA(char * szFormat, ...);
std::string Utf82ansi(const std::string& strUtf8);
std::string ansi2Utf8(const std::string& strAnsi);
std::string unicode2Utf8(const std::wstring& strUnicode);
private:
BOOL GetUrlParam(
const char * pcUrl,
std::string & strServerOnUrl,
std::string & strBodyOnUrl);
};
#endif // #ifndef __HTTP_POST_H__
/// @file httpPost.cpp
/// @brief ...
#include "stdafx.h"
#include "httpPost.h"
CHttpPost::CHttpPost()
{
}
CHttpPost::~CHttpPost()
{
}
BOOL CHttpPost::PostDataToWebA(
const char* pcUrl,
const char* pcDataToPostA,
std::string& strDataReturnFromWeb)
{
USES_CONVERSION;
const char* szAccept[] = {"Accept: */*", NULL}; //接受文件的类型
const char strHeaders[] = "Content-Type: application/x-www-form-urlencoded\r\n";
const char szAgent[] = "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; .NET CLR 2.0.50727; .NET CLR 3.0.04506.648; .NET CLR 3.5.8888.8888;)";
BOOL bRc = FALSE;
BOOL bReadOk = FALSE;
HRESULT hRc = S_FALSE;
DWORD dwBytesRead = 0;
char szRecv[MAX_PATH] = {'\0'};
std::string strServerOnUrl = "";
std::string strBodyOnUrl = "";
std::string strDataToPostUtf8 = "";
HINTERNET hSession = NULL;
HINTERNET hConnect = NULL;
HINTERNET hRequest = NULL;
strDataReturnFromWeb = "";
if (!GetUrlParam(pcUrl, strServerOnUrl, strBodyOnUrl))
return FALSE;
/// Post的数据中有可能有宽字符, 所以要转成utf8, 再post
strDataToPostUtf8 = ansi2Utf8((NULL != pcDataToPostA) ? pcDataToPostA : "");
// 初始化 WinInet.dll 并联接服务器,返回相应的句柄
hSession = InternetOpenA(szAgent, INTERNET_OPEN_TYPE_PRECONFIG,NULL,NULL,0);
if ( hSession )
{
//建立 Internet 的连接,开始 HTTP会话
hConnect = InternetConnectA(hSession, strServerOnUrl.c_str(), INTERNET_DEFAULT_HTTP_PORT,NULL,NULL,INTERNET_SERVICE_HTTP,0,1);
if (hConnect)
{
//打开一个 HTTP 请求的句柄
hRequest = HttpOpenRequestA(
hConnect,
"POST",
strBodyOnUrl.c_str(),
"HTTP/1.1",
NULL,
(LPCSTR *)&szAccept,
INTERNET_FLAG_RELOAD,
1);
if ( hRequest )
{
// 提交数据表单
if (HttpSendRequestA(hRequest, strHeaders, strlen(strHeaders), (void*)strDataToPostUtf8.c_str(), strlen(strDataToPostUtf8.c_str())))
{
while (1)
{
::ZeroMemory(szRecv, sizeof(szRecv));
bReadOk = InternetReadFile( hRequest , (LPBYTE)szRecv , sizeof(szRecv), &dwBytesRead);
if (!bReadOk || (0 == dwBytesRead))
break;
/// 假设得到的都是可见字符
bRc = TRUE;
strDataReturnFromWeb += szRecv;
};
/// 特殊情况的处理
// 起始字符3个 : ef bb bf, 过滤掉. e.g. 有些php页面回答的内容长度为0, 也有这3个二进制字符
if ( dwBytesRead != 0 )
{
if ((dwBytesRead >= 3)
&& ((UCHAR)0xef == (UCHAR)strDataReturnFromWeb[0])
&& ((UCHAR)0xbb == (UCHAR)strDataReturnFromWeb[1])
&& ((UCHAR)0xbf == (UCHAR)strDataReturnFromWeb[2]))
{
strDataReturnFromWeb = strDataReturnFromWeb.substr(3, -1);
}
else
strDataReturnFromWeb = szRecv;
}
}
InternetCloseHandle(hConnect);
}
InternetCloseHandle(hConnect);
}
InternetCloseHandle(hSession);
}
return bRc;
}
BOOL CHttpPost::GetUrlParam(const char * pcUrl, std::string & strServerOnUrl, std::string & strBodyOnUrl)
{
USES_CONVERSION;
BOOL bRc = FALSE;
size_t nPos = std::string::npos;
HRESULT hRc = S_FALSE;
std::wstring strUrlW = L"";
std::string strUrl = "";
PARSEDURLA pu;
strServerOnUrl = "";
strBodyOnUrl = "";
if (NULL == pcUrl)
goto END_GetUrlParam;
strUrlW = A2W(pcUrl);
hRc = ::IsValidURL(NULL, strUrlW.c_str(), 0);
if (S_OK != hRc)
goto END_GetUrlParam;
pu.cbSize = sizeof(pu);
hRc = ParseURLA(pcUrl, &pu);
if (S_OK != hRc)
goto END_GetUrlParam;
/// we only execute http post
if (URL_SCHEME_HTTP != pu.nScheme)
goto END_GetUrlParam;
strUrl = pu.pszSuffix;
nPos = strUrl.find("//");
if ((std::string::npos == nPos) || (0 != nPos))
goto END_GetUrlParam;
strUrl = strUrl.substr(2, -1);
nPos = strUrl.find("/");
if (std::string::npos == nPos)
goto END_GetUrlParam;
strServerOnUrl = strUrl.substr(0, nPos);
strBodyOnUrl = strUrl.substr(nPos, -1);
bRc = TRUE;
END_GetUrlParam:
return bRc;
}
std::wstring CHttpPost::StringFormatV(WCHAR * szFormat, ...)
{//入参为格式化的参数列表
size_t nStrLen = 0;
WCHAR * pBufMsg = NULL;
std::wstring strRc;
va_list args;
va_start(args, szFormat);
nStrLen = _vsntprintf(NULL, 0, szFormat, args);
pBufMsg = new WCHAR[nStrLen + 1];
_ASSERT(pBufMsg);
::ZeroMemory(pBufMsg, (nStrLen + 1) * sizeof(WCHAR));
nStrLen = _vsntprintf(pBufMsg, nStrLen, szFormat, args);
va_end(args);
strRc = pBufMsg;
delete []pBufMsg;
pBufMsg = NULL;
return strRc;
}
std::string CHttpPost::StringFormatVA(char * szFormat, ...)
{//入参为格式化的参数列表
size_t nStrLen = 0;
char * pBufMsg = NULL;
std::string strRc;
va_list args;
va_start(args, szFormat);
nStrLen = _vsnprintf(NULL, 0, szFormat, args);
pBufMsg = new char[nStrLen + 1];
_ASSERT(pBufMsg);
::ZeroMemory(pBufMsg, nStrLen + 1);
nStrLen = _vsnprintf(pBufMsg, nStrLen, szFormat, args);
va_end(args);
strRc = pBufMsg;
delete []pBufMsg;
pBufMsg = NULL;
return strRc;
}
std::string CHttpPost::ansi2Utf8(const std::string& strAnsi)
{
int iLen = 0;
WCHAR* pcAnsiW = NULL;
std::wstring strW = L"";
std::string strUtf8Out = "";
iLen = MultiByteToWideChar(CP_ACP, 0, strAnsi.c_str(), -1, NULL, NULL);
if (iLen <= 0)
goto END_ansi2Utf8;
pcAnsiW = new WCHAR[iLen + 1];
if (NULL == pcAnsiW)
goto END_ansi2Utf8;
ZeroMemory(pcAnsiW, (iLen + 1) * sizeof(WCHAR));
iLen = MultiByteToWideChar(CP_ACP, 0, strAnsi.c_str(), -1, pcAnsiW, iLen);
if (iLen <= 0)
goto END_ansi2Utf8;
strW = pcAnsiW;
strUtf8Out = unicode2Utf8(strW);
END_ansi2Utf8:
SAFE_DELETE_ARRAY(pcAnsiW);
return strUtf8Out;
}
std::string CHttpPost::unicode2Utf8(const std::wstring& strUnicode)
{
int iLen = 0;
char* pcAnsiA = NULL;
std::string strOutUtf8 = "";
iLen = WideCharToMultiByte(CP_UTF8, 0, strUnicode.c_str(), -1, NULL, 0, NULL, NULL);
if (iLen <= 0)
goto END_unicode2Utf8;
pcAnsiA = new char[iLen + 1];
if (NULL == pcAnsiA)
goto END_unicode2Utf8;
ZeroMemory(pcAnsiA, iLen + 1);
iLen = WideCharToMultiByte(CP_UTF8, 0, strUnicode.c_str(), -1, pcAnsiA, iLen, NULL, NULL);
if (iLen <= 0)
goto END_unicode2Utf8;
strOutUtf8 = pcAnsiA;
END_unicode2Utf8:
SAFE_DELETE_ARRAY(pcAnsiA);
return strOutUtf8;
}
std::string CHttpPost::Utf82ansi(const std::string& strUtf8)
{
USES_CONVERSION;
int iLen = 0;
WCHAR* pcAnsiW = NULL;
std::string strAnsiOut = "";
iLen = MultiByteToWideChar(CP_UTF8, 0, strUtf8.c_str(), -1, NULL, NULL);
if (iLen <= 0)
goto END_Utf82ansi;
pcAnsiW = new WCHAR[iLen + 1];
if (NULL == pcAnsiW)
goto END_Utf82ansi;
ZeroMemory(pcAnsiW, (iLen + 1) * sizeof(WCHAR));
iLen = MultiByteToWideChar(CP_ACP, 0, strUtf8.c_str(), -1, pcAnsiW, iLen);
if (iLen <= 0)
goto END_Utf82ansi;
strAnsiOut = W2A(pcAnsiW);
END_Utf82ansi:
SAFE_DELETE_ARRAY(pcAnsiW);
return strAnsiOut;
}