天天看點

C++通過HTTP請求Get或Post方式請求Json資料

http://www.cnblogs.com/shike8080/p/6549339.html

http://www.cnblogs.com/liaocheng/p/4243731.html 

#pragma once
#include <iostream>
#include <windows.h>
#include <wininet.h>

using namespace std;

//每次讀取的位元組數
#define READ_BUFFER_SIZE        4096

enum HttpInterfaceError
{
    Hir_Success = 0,        //成功
    Hir_InitErr,            //初始化失敗
    Hir_ConnectErr,            //連接配接HTTP伺服器失敗
    Hir_SendErr,            //發送請求失敗
    Hir_QueryErr,            //查詢HTTP請求頭失敗
    Hir_404,                //頁面不存在
    Hir_IllegalUrl,            //無效的URL
    Hir_CreateFileErr,        //建立檔案失敗
    Hir_DownloadErr,        //下載下傳失敗
    Hir_QueryIPErr,            //擷取域名對應的位址失敗
    Hir_SocketErr,            //套接字錯誤
    Hir_UserCancel,            //使用者取消下載下傳
    Hir_BufferErr,            //檔案太大,緩沖區不足
    Hir_HeaderErr,            //HTTP請求頭錯誤
    Hir_ParamErr,            //參數錯誤,空指針,空字元
    Hir_UnknowErr,
};
enum HttpRequest
{
    Hr_Get,
    Hr_Post
};
class CWininetHttp
{
public:
    CWininetHttp(void);
    ~CWininetHttp(void);

public:
    //  通過HTTP請求:Get或Post方式擷取JSON資訊 [3/14/2017/shike]
    const std::string RequestJsonInfo( const std::string& strUrl,
                                HttpRequest type = Hr_Get, 
                                 std::string lpHeader = "",
                                 std::string lpPostData = "");
protected:
    // 解析卡口Json資料 [3/14/2017/shike]
    void ParseJsonInfo(const std::string &strJsonInfo);

    // 關閉句柄 [3/14/2017/shike]
    void Release();

    // 釋放句柄 [3/14/2017/shike]
    void ReleaseHandle( HINTERNET& hInternet );

    // 解析URL位址 [3/14/2017/shike]
    void ParseURLWeb( std::string strUrl, std::string& strHostName, std::string& strPageName, WORD& sPort);

    // UTF-8轉為GBK2312 [3/14/2017/shike]
    char* UtfToGbk(const char* utf8);

private:
    HINTERNET            m_hSession;
    HINTERNET            m_hConnect;
    HINTERNET            m_hRequest;
    HttpInterfaceError    m_error;
};
           
/*************************************************
File name  :  WininetHttp.cpp
Description:  通過URL通路HTTP請求方式擷取JSON
Author     :  shike
Version    :  1.0
Date       :  2016/10/27
Copyright (C) 2016 -  All Rights Reserved
*************************************************/
#include "WininetHttp.h"
//#include "Common.h"
#include <json/json.h>
#include <fstream>
#include "common/CVLog.h"
#pragma comment(lib, "Wininet.lib")
#include <tchar.h>
using namespace std;

extern CCVLog CVLog;

CWininetHttp::CWininetHttp(void):m_hSession(NULL),m_hConnect(NULL),m_hRequest(NULL)
{
}

CWininetHttp::~CWininetHttp(void)
{
    Release();
}

//  通過HTTP請求:Get或Post方式擷取JSON資訊 [3/14/2017/shike]
const std::string CWininetHttp::RequestJsonInfo(const std::string& lpUrl,
                                                HttpRequest type/* = Hr_Get*/,
                                                std::string strHeader/*=""*/,
                                                std::string strPostData/*=""*/)
{
    std::string strRet = "";
    try
    {
        if ( lpUrl.empty())
        {
            throw Hir_ParamErr;
        }
        Release();
        m_hSession = InternetOpen(_T("Http-connect"), INTERNET_OPEN_TYPE_PRECONFIG, NULL, NULL, NULL);    //局部

        if ( NULL == m_hSession )
        {
            throw Hir_InitErr;
        }

        INTERNET_PORT port    = INTERNET_DEFAULT_HTTP_PORT;
        std::string strHostName = "";
        std::string strPageName = "";

        ParseURLWeb(lpUrl, strHostName, strPageName, port);
        printf("lpUrl:%s,\nstrHostName:%s,\nstrPageName:%s,\nport:%d\n",lpUrl.c_str(),strHostName.c_str(),strPageName.c_str(),(int)port);

        m_hConnect = InternetConnectA(m_hSession, strHostName.c_str(), port, NULL, NULL, INTERNET_SERVICE_HTTP, NULL, NULL);

        if ( NULL == m_hConnect )
        {
            throw Hir_ConnectErr;
        }

        std::string strRequestType;
        if ( Hr_Get == type )
        {
            strRequestType = "GET";
        }
        else
        {
            strRequestType = "POST";
        }

        m_hRequest = HttpOpenRequestA(m_hConnect,strRequestType.c_str(), strPageName.c_str(),"HTTP/1.1", NULL, NULL, INTERNET_FLAG_RELOAD, NULL);
        if ( NULL == m_hRequest )
        {
            throw Hir_InitErr;
        }

        DWORD dwHeaderSize = (strHeader.empty()) ? 0 : strlen(strHeader.c_str());
        BOOL bRet = FALSE;
        if ( Hr_Get == type )
        {
            bRet = HttpSendRequestA(m_hRequest,strHeader.c_str(),dwHeaderSize,NULL, 0);
        }
        else
        {
            DWORD dwSize = (strPostData.empty()) ? 0 : strlen(strPostData.c_str());
            bRet = HttpSendRequestA(m_hRequest,strHeader.c_str(),dwHeaderSize,(LPVOID)strPostData.c_str(), dwSize);
        }
        if ( !bRet )
        {
            throw Hir_SendErr;
        }

        char szBuffer[READ_BUFFER_SIZE + 1] = {0};
        DWORD dwReadSize = READ_BUFFER_SIZE;
        if ( !HttpQueryInfoA(m_hRequest, HTTP_QUERY_RAW_HEADERS, szBuffer, &dwReadSize, NULL) )
        {
            throw Hir_QueryErr;
        }
        if ( NULL != strstr(szBuffer, "404") )
        {
            throw Hir_404;
        }

        while( true )
        {
            bRet = InternetReadFile(m_hRequest, szBuffer, READ_BUFFER_SIZE, &dwReadSize);
            if ( !bRet || (0 == dwReadSize) )
            {
                break;
            }
            szBuffer[dwReadSize]='\0';
            strRet.append(szBuffer);
        }
    }
    catch(HttpInterfaceError error)
    {
        m_error = error;
    }
    return std::move(strRet);
}

// 解析Json資料 [11/8/2016/shike]
void CWininetHttp::ParseJsonInfo(const std::string &strJsonInfo)
{
    Json::Reader reader;                                    //解析json用Json::Reader
    Json::Value value;                                        //可以代表任意類型
    if (!reader.parse(strJsonInfo, value))  
    {  
        CVLog.LogMessage(LOG_LEVEL_ERROR,"[CXLDbDataMgr::GetVideoGisData] Video Gis parse data error...");
    }
    if (!value["result"].isNull())        
    {
        int nSize = value["result"].size();
        for(int nPos = 0; nPos < nSize; ++nPos)                //對資料數組進行周遊
        {
            //PGCARDDEVDATA stru ;
            //stru.strCardName        = value["result"][nPos]["tollgateName"].asString();
            //stru.strCardCode        = value["result"][nPos]["tollgateCode"].asString();
            //std::string strCDNum    = value["result"][nPos]["laneNumber"].asString();    //增加:車道總數
            //stru.nLaneNum            = atoi(strCDNum.c_str());
            //std::string strLaneDir    = value["result"][nPos]["laneDir"].asString();        //增加:車道方向,進行規則轉換
            //stru.strLaneDir            = TransformLaneDir(strLaneDir);
            //stru.dWgs84_x            = value["result"][nPos]["wgs84_x"].asDouble();
            //stru.dWgs84_y            = value["result"][nPos]["wgs84_y"].asDouble();
            //stru.dMars_x            = value["result"][nPos]["mars_x"].asDouble();
            //stru.dMars_y            = value["result"][nPos]["mars_y"].asDouble();
            //lstCardDevData.emplace_back(stru);
        }
    }
}

// 解析URL位址 [3/14/2017/shike]
void CWininetHttp::ParseURLWeb( std::string strUrl, std::string& strHostName, std::string& strPageName, WORD& sPort)
{
    sPort = 80;
    string strTemp(strUrl);
    std::size_t nPos = strTemp.find("http://");
    if (nPos != std::string::npos)
    {
        strTemp = strTemp.substr(nPos + 7, strTemp.size() - nPos - 7);
    }

    nPos = strTemp.find('/');
    if ( nPos == std::string::npos )    //沒有找到
    {
        strHostName = strTemp;
    }
    else
    {
        strHostName = strTemp.substr(0, nPos);
    }

    std::size_t nPos1 = strHostName.find(':');
    if ( nPos1 != std::string::npos )
    {
        std::string strPort = strTemp.substr(nPos1 + 1, strHostName.size() - nPos1 - 1);
        strHostName = strHostName.substr(0, nPos1);
        sPort = (WORD)atoi(strPort.c_str());
    }
    if ( nPos == std::string::npos )
    {
        return ;
    }
    strPageName = strTemp.substr(nPos, strTemp.size() - nPos);
}

// 關閉句柄 [3/14/2017/shike]
void CWininetHttp::Release()
{
    ReleaseHandle(m_hRequest); 
    ReleaseHandle(m_hConnect); 
    ReleaseHandle(m_hSession);
}

// 釋放句柄 [3/14/2017/shike]
void CWininetHttp::ReleaseHandle( HINTERNET& hInternet )
{
    if (hInternet) 
    { 
        InternetCloseHandle(hInternet); 
        hInternet = NULL; 
    }
}

// UTF-8轉為GBK2312 [3/14/2017/shike]
char* CWininetHttp::UtfToGbk(const char* utf8)
{
    int len = MultiByteToWideChar(CP_UTF8, 0, utf8, -1, NULL, 0);
    wchar_t* wstr = new wchar_t[len+1];
    memset(wstr, 0, len+1);
    MultiByteToWideChar(CP_UTF8, 0, utf8, -1, wstr, len);
    len = WideCharToMultiByte(CP_ACP, 0, wstr, -1, NULL, 0, NULL, NULL);
    char* str = new char[len+1];
    memset(str, 0, len+1);
    WideCharToMultiByte(CP_ACP, 0, wstr, -1, str, len, NULL, NULL);
    if(wstr) delete[] wstr;
    return str;
}
           

WinInet實作的HTTP接口/WinHttp實作的HTTP接口/Socket實作的HTTP接口/下載下傳檔案,使用回調接口擷取下載下傳進度,這些代碼可以在開源中擷取到;

轉載我的csdn網址:http://download.csdn.net/my