/** @file JCCurlWrap.h @brief @author hugao @version 1.0 @date 2016_5_11 */ #ifndef __JCCurlWrap_H__ #define __JCCurlWrap_H__ // 这个宏指示是在使用 CURL 的静态库,必须要有 #define CURL_STATICLIB #ifdef __cplusplus extern "C" { #endif #include #ifdef __cplusplus } #endif #include #include #include #include #include namespace laya{ class __Buffer{ public: __Buffer(){ m_pBuffer = 0; m_iDataSize = m_iBufferSize = 0; } ~__Buffer(){ if( 0 != m_pBuffer ){ delete[] m_pBuffer; m_pBuffer = 0; } } char *SwapBuff( char *p_pBuff, size_t p_iBuffSize, size_t p_iDataSize=0 ){ char *pRet = m_pBuffer; m_pBuffer = p_pBuff; m_iBufferSize = p_iBuffSize; m_iDataSize = p_iDataSize; return pRet; } size_t GetDataSize(){ return m_iDataSize; } char *GetData(){ if( 0 == m_iDataSize ) return 0; else return m_pBuffer; } void ClearData(){ m_iDataSize = 0; } size_t GetFreeSize(){ return (m_iBufferSize-m_iDataSize); } void AddData( const void *p_pData, size_t p_iSize ){ for(;GetFreeSize() 0){ memcpy(pBuff, m_pBuffer, m_iDataSize); } delete[] m_pBuffer; } m_pBuffer = pBuff; } private: char *m_pBuffer; size_t m_iDataSize; size_t m_iBufferSize; }; class Curl{ protected: typedef int (*WRITECALLBACK)(void *p_pDataBuffer, size_t p_size, size_t p_nmemb, void *p_pUserData); typedef int (*PROGRESSCALLBACK)(void *clientp, curl_off_t dltotal, curl_off_t dlnow, curl_off_t ultotal, curl_off_t ulnow); typedef size_t(*HEADERCALLBACK)(void *ptr, size_t size, size_t nmemb, void *data); public: //进度的回调。返回1则中止。参数是total,now, speed, userdata typedef int(*FuncOnProg)(unsigned int, unsigned int, float, void*); Curl(); ~Curl(); static void global_init(); bool Init( ); void Release(); void setProgressCB(FuncOnProg cb, void* userData) { m_pExtOnProg = cb; m_pExtOnProgData = userData; } Curl& begin(); Curl& end(); Curl& set_GET(); Curl& set_POST(); Curl& set_Url(const char* pUrl); Curl& set_CookieList(const char* pC); Curl& set_CookieFile(const char* pFile); //是否自动重定向 Curl& set_FollowLocation(long v); //设置超时。单位秒 Curl& set_Timeout(long v); // 连接超时时间 秒 Curl& set_ConnectTimeout(long v); Curl& set_OnData(WRITECALLBACK func, void* pUserData); Curl& set_EnableProg(bool b); Curl& set_UserAgent(const char* pAgent);//这个也可以通过header来设置? Curl& set_PostData(const char* pPostData, int nPostLen); //只要header? Curl& set_OnlyHead(bool b); void ApplyHeaders(); //设置header,每次用完后会自动清理 void set_Header( const std::vector& p_headers ){m_headers = p_headers;}; //检查当前任务的返回值。触发对应的回调。 bool checkResult(const char *p_pszUrl); //通用的下载请求 void query(const char *p_pszUrl, __Buffer **p_ppResBuff, const char* p_pPostData, int p_nPostLen, //可以为0 bool p_bOnlyHeader, //一般是false int p_nTimeout, int p_nConnTimeout, //为0则缺省 const std::vector& p_vHeaders, //size()==0则忽略 const char* p_pLocalFile, //一边下载,一边保存,一般用在大文件下载,0则忽略 bool p_bChkRemoteChange //检查远端文件是否改变了,大文件用 ); //如果有 p_pPostData,则在 CURLOPT_POSTFIELDS 发送数据 void query( const char *p_pszUrl, __Buffer **p_ppResBuff, const char* p_pPostData, int p_nPostLen); void downloadBigFile(const char *p_pszUrl, const char* p_pszLocal, int p_nOptTimeout); void downloadHeader(const char *p_pszUrl, __Buffer **p_ppResBuff, int p_nOptTimeout); //发送一个只有一个 data 字段的数据 void PostMultipart( const char *p_pszUrl, __Buffer **p_ppResBuff, const char* p_pUserName, const char* p_pPostData, int p_nPostDataLen ); //上传文件。 void upload(const char *p_pszUrl, __Buffer **p_ppResBuff, const char* p_pUserName, const char* p_pszFile ); //发送一个带一个二进制buffer的formdata。 //二进制数据对应的formdata的名字是 p_pDataName //formdata 是其他字段,每两个为一对。 void _PostMultipart( const char *p_pszUrl, __Buffer **p_ppResBuff, std::vector& formdata, const char* p_pDataName,const char* p_pPostData, int p_nPostDataLen); //设置curl的cookie文件 void setCookieFile( const char* p_pszCookieFile ); void setProxyString(const char* p_pszProxy); static int _ProgressCallback(void *clientp, curl_off_t dltotal, curl_off_t dlnow, curl_off_t ultotal, curl_off_t ulnow); protected: bool _Prepare(); static int _WriteCallback(void *p_pDataBuffer, size_t p_size, size_t p_nmemb, void *p_pUserData); public: static std::vector NoHeader; static bool s_bUseCurlCookie; long m_nLocalFileLen = 0; //本地文件的长度。用于断点续传。 //下面是返回结果 std::string m_strSvAddr; //服务器地址 std::string m_strLocalAddr; int m_nCurlRet = 0; long m_nResponseCode = 0; std::string m_strResponseHead; //响应的header protected: CURL * m_pCurlHandle; int m_nOptTimeout; __Buffer m_Buffer; double m_tmTaskBegin; curl_off_t m_dDownedSize; curl_off_t m_dLastDownedSize; double m_tmLastProg; double m_tmLastNotify; bool m_bStopAndRetry; //停止当前任务,重新尝试 std::vector m_headers; //每一个都是 key:value //传了一部分后没有反应的检测 double m_tmLastHasData; //上次接收到数据的时间 std::string m_strCookieFile; struct curl_slist *m_pslist = nullptr; FuncOnProg m_pExtOnProg = nullptr; void* m_pExtOnProgData = nullptr; }; } //------------------------------------------------------------------------------ #endif //__JCCurlWrap_H__ //-----------------------------END FILE--------------------------------