http post 的封装类

  • 时间:
  • 来源:互联网
  • 文章标签:

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;
}



本文链接http://www.taodudu.cc/news/show-647558.html