libcurl開源庫封裝ftp工具,支持多線程併發、斷點續傳、超時連接、傳輸速率控制

各位朋友好,第一次在CSDN寫博客,後續時間充足的話會陸續更新一些資源,大家一起探討交流,感謝!!!
如有任何疑問,可以留言。

目的:再次封裝CURL接口,使用FTP相關接口更方便,更易懂
功能: 可支持多線程同時下載,對外接口全封裝在FtpServe子類中(FtpServe繼承CLib_Curl類目的是爲以後便於擴展其他接口協議eg:HTTP等),用戶只需要定義對象,設置好遠程服務器URL和用戶名密碼(也可根據需要改成匿名登錄)即可啓動一個服務來工作。

#ifndef _LIBCURL_H_
#define _LIBCURL_H_

#include <curl/curl.h>
#include <string>

#define QH_Debug(fmt...) do {printf("[%s:%d]: ", __FUNCTION__, __LINE__);printf(fmt);}while(0)

using std::string;

typedef size_t (*HeaderFun_Curl_t)(void *, size_t, size_t, void *);


class CLibcurlCallback
{
public:
	virtual void Progress(void* lpParam, double dTotal, double bLoaded) = 0;
};

enum LibcurlFlag
{
	Lf_None = 0,
	Lf_Download,
	Lf_Post,
	Lf_Get,
};

typedef enum  
{
    Un_INIT         = 0x00, //未初始化
    Err_INIT        = 0x01, //初始化失敗
    Already_INIT    = 0x02, //已初始化
}CURL_GLOBAL_INIT_e;

class CLib_Curl
{
public:
    CLib_Curl(void);
    ~CLib_Curl(void);
    inline static CLib_Curl* GetInstance();
    bool Set_Timeout(CURL *pstCurl, int s32Second); //設置總執行超時(秒)
	bool Set_ConnectTimeout(CURL *pstCurl, int s32Second); //設置連接超時(秒)
    bool Set_URL(CURL *pstCurl, const char *pRemoteService); //設置遠程服務地址
    bool Set_UserPwd(CURL *pstCurl, const char *pUsrePwd); //設置遠程服務用戶名密碼 
    bool Set_HeaderFun(CURL *pstCurl, unsigned long *pu32FileSize, HeaderFun_Curl_t pCallBacks); //設置頭處理函數
    bool Set_WriteFun(CURL *pstCurl, FILE *pFp, HeaderFun_Curl_t pCallBacks); //設置保存文件函數
    bool Set_ResumeFrom(CURL *pstCurl, curl_off_t Pos); //設置斷點續傳起始位置
    bool Set_ResumeFromLarge(CURL *pstCurl, curl_off_t Pos);	 //設置斷點續傳起始位置,針對大文件
    bool Set_TransferSpeed(CURL *pstCurl, unsigned long u32Second, unsigned long u32Size); //設置單位時間傳輸速率
    bool Set_ProgressBar(CURL *pstCurl, bool bSwitch); //進度條開關 false:關,true:開
    bool Set_DebugInfo(CURL *pstCurl, bool bSwitch); //調試信息 false:關,true:開
	bool Set_NoBody(CURL *pstCurl, bool bSwitch); //不想在輸出中包含body部分,設置參數爲真
	bool CurlInfo_ContentLength(CURL *pstCurl, double *pSize); //獲取文件大小
	bool Perform_CurlHandle(CURL *pstCurl); //執行CURL操作
    CURL* Init_CurlHandle(void); //初始化curl指針
    void Clean_CurlHandle(CURL *pstCurl); //銷燬curl指針
    const char* GetError()const; //獲取錯誤詳細信息

public:
    
protected:
    CURLcode m_curlCode;

private:

private:
    //static CLib_Curl* m_pInstance;
    static pthread_mutex_t m_Mutex;
};

#endif


/************************************************************
*FileName: LibCurl.cpp
*Date:     2019.07.13
*Author:   qiuhui
*Version:  V1.0
*Description:(LibCURL)庫接口再封裝
*Others:
*History:   
***********************************************************/
#include "LibCurl.h"

//CLib_Curl* CLib_Curl::m_pInstance = new CLib_Curl;
CURL_GLOBAL_INIT_e CLib_Curl::m_esInitFlag = Un_INIT;
pthread_mutex_t CLib_Curl::m_Mutex=PTHREAD_MUTEX_INITIALIZER;

CLib_Curl::CLib_Curl(void)
{
	pthread_mutex_lock(&m_Mutex);
	if (Already_INIT != CLib_Curl::m_esInitFlag)
	{
		QH_Debug("CURL全局初始化\r\n");
		m_curlCode = curl_global_init(CURL_GLOBAL_ALL);
		if (CURLE_OK != m_curlCode)
		{
			CLib_Curl::m_esInitFlag = Err_INIT;
			QH_Debug("CURL全局初始化失敗\r\n");
		}
		else
		{
			CLib_Curl::m_esInitFlag = Already_INIT;
			QH_Debug("CURL全局初始化成功\r\n");
		}
	}
	pthread_mutex_unlock(&m_Mutex);
}

CLib_Curl::~CLib_Curl(void)
{
	//curl_global_cleanup(); //整個進程全局只初始化一次,故不考慮析構函數執行curl_global_cleanup()
}

CLib_Curl* CLib_Curl::GetInstance()
{
	return NULL;//m_pInstance;
}


bool CLib_Curl::Set_Timeout(CURL *pstCurl, int s32Second)
{
	if ((NULL==pstCurl) || (s32Second<0))
	{
		QH_Debug("parameter Failed:%p,%d\r\n",pstCurl, s32Second);
		return false;
	}
	
	m_curlCode = curl_easy_setopt(pstCurl, CURLOPT_TIMEOUT, s32Second);
	return CURLE_OK == m_curlCode;
}

bool CLib_Curl::Set_ConnectTimeout(CURL *pstCurl, int s32Second)
{
	if ((NULL==pstCurl) || (s32Second<0))
	{
		QH_Debug("parameter Failed:%p,%d\r\n",pstCurl, s32Second);
		return false;
	}
	
	m_curlCode = curl_easy_setopt(pstCurl, CURLOPT_CONNECTTIMEOUT, s32Second);
	return CURLE_OK == m_curlCode;
}

bool CLib_Curl::Set_URL(CURL *pstCurl, const char *pRemoteService)
{
	if ((NULL==pstCurl) || (NULL==pRemoteService))
	{
		QH_Debug("parameter Failed:%p,%s\r\n",pstCurl, pRemoteService);
		return false;
	}
	
	m_curlCode = curl_easy_setopt(pstCurl, CURLOPT_URL, pRemoteService);
	return CURLE_OK == m_curlCode;
}

bool CLib_Curl::Set_UserPwd(CURL *pstCurl, const char *pUsrePwd)
{
	if ((NULL==pstCurl) || (NULL==pUsrePwd))
	{
		QH_Debug("parameter Failed:%p,%s\r\n",pstCurl, pUsrePwd);
		return false;
	}
	
	m_curlCode = curl_easy_setopt(pstCurl, CURLOPT_USERPWD, pUsrePwd);
	return CURLE_OK == m_curlCode;
}

bool CLib_Curl::Set_HeaderFun(CURL *pstCurl, unsigned long *pu32FileSize, HeaderFun_Curl_t pCallBacks)
{
	if ((NULL==pstCurl) || (NULL==pu32FileSize) || (NULL==pCallBacks))
	{
		QH_Debug("parameter Failed:%p,%p,%p\r\n",pstCurl, pu32FileSize, pCallBacks);
		return false;
	}
	
	m_curlCode = curl_easy_setopt(pstCurl, CURLOPT_HEADERFUNCTION, pCallBacks);
	if (CURLE_OK != m_curlCode)
	{
		return false;
	}
	
    m_curlCode = curl_easy_setopt(pstCurl, CURLOPT_HEADERDATA, pu32FileSize);//pu32FileSize->pCallBacks第四個參數賦值
	return CURLE_OK == m_curlCode;
}

bool CLib_Curl::Set_WriteFun(CURL *pstCurl, FILE *pFp, HeaderFun_Curl_t pCallBacks)
{
	if ((NULL==pstCurl) || (NULL==pFp) || (NULL==pCallBacks))
	{
		QH_Debug("parameter Failed:%p,%p,%p\r\n",pstCurl, pFp, pCallBacks);
		return false;
	}
	
	m_curlCode = curl_easy_setopt(pstCurl, CURLOPT_WRITEFUNCTION, pCallBacks);
	if (CURLE_OK != m_curlCode)
	{
		return false;
	}
	
	m_curlCode = curl_easy_setopt(pstCurl, CURLOPT_WRITEDATA, pFp);//要想回調函數保存數據,第3個參數必須是個FILE指針
	return CURLE_OK == m_curlCode;
}

bool CLib_Curl::Set_ResumeFrom(CURL *pstCurl, curl_off_t Pos)
{
	if ((NULL==pstCurl) || (Pos<0))
	{
		QH_Debug("parameter Failed:%p,%lld\r\n",pstCurl, Pos);
		return false;
	}
		
	m_curlCode = curl_easy_setopt(pstCurl, CURLOPT_RESUME_FROM, Pos);
	return CURLE_OK == m_curlCode;
}

bool CLib_Curl::Set_ResumeFromLarge(CURL *pstCurl, curl_off_t Pos)
{
	if ((NULL==pstCurl) || (Pos<0))
	{
		QH_Debug("parameter Failed:%p,%lld\r\n",pstCurl, Pos);
		return false;
	}
	QH_Debug("Breakpoint Offset:%lld\r\n", Pos);
	m_curlCode = curl_easy_setopt(pstCurl, CURLOPT_RESUME_FROM_LARGE, Pos);
	return CURLE_OK == m_curlCode;
}

bool CLib_Curl::Set_TransferSpeed(CURL *pstCurl, unsigned long u32Second, unsigned long u32Size)
{
	if (NULL == pstCurl)
	{
		QH_Debug("parameter Failed:%p\r\n",pstCurl);
		return false;
	}
		
	m_curlCode = curl_easy_setopt(pstCurl, CURLOPT_LOW_SPEED_TIME, u32Second); //設置時間閥值 單位秒
	if (CURLE_OK != m_curlCode)
	{
		return false;
	}
	
  	m_curlCode = curl_easy_setopt(pstCurl, CURLOPT_LOW_SPEED_LIMIT, u32Size); //設置最低傳輸字節數
	return CURLE_OK == m_curlCode;
}

bool CLib_Curl::Set_ProgressBar(CURL *pstCurl, bool bSwitch)
{
	if (NULL == pstCurl)
	{
		QH_Debug("parameter Failed:%p\r\n",pstCurl);
		return false;
	}
	
	m_curlCode = curl_easy_setopt(pstCurl, CURLOPT_NOPROGRESS, (bSwitch==true?0L:1L));
	return CURLE_OK == m_curlCode;
}

bool CLib_Curl::Set_DebugInfo(CURL *pstCurl, bool bSwitch)
{
	if (NULL == pstCurl)
	{
		QH_Debug("parameter Failed:%p\r\n",pstCurl);
		return false;
	}
	
	m_curlCode = curl_easy_setopt(pstCurl, CURLOPT_VERBOSE, (bSwitch==false?0L:1L));
	return CURLE_OK == m_curlCode;
}

bool CLib_Curl::Set_NoBody(CURL *pstCurl, bool bSwitch)
{
	if ((NULL == pstCurl))
	{
		QH_Debug("parameter Failed:%p\r\n",pstCurl);
		return false;
	}
		
	m_curlCode = curl_easy_setopt(pstCurl, CURLOPT_NOBODY, (bSwitch==false?0L:1L));
	return CURLE_OK == m_curlCode;
}

bool CLib_Curl::CurlInfo_ContentLength(CURL *pstCurl, double *pSize)
{
	if ((NULL==pstCurl) || (NULL==pSize))
	{
		QH_Debug("parameter Failed:%p,%p\r\n",pstCurl,pSize);
		return false;
	}
		
	m_curlCode = curl_easy_getinfo(pstCurl, CURLINFO_CONTENT_LENGTH_DOWNLOAD, pSize);
	return CURLE_OK == m_curlCode;
}


bool CLib_Curl::Perform_CurlHandle(CURL *pstCurl)
{
	if (NULL == pstCurl)
	{
		QH_Debug("parameter Failed:%p\r\n",pstCurl);
		return false;
	}
	
	m_curlCode= curl_easy_perform(pstCurl);
	QH_Debug("m_curlCode:%d\r\n",m_curlCode);
	return CURLE_OK == m_curlCode;
}

CURL* CLib_Curl::Init_CurlHandle(void)
{
	return curl_easy_init();
}

void CLib_Curl::Clean_CurlHandle(CURL *pstCurl)
{
	if (NULL == pstCurl)
	{
		QH_Debug("parameter Failed:%p\r\n",pstCurl);
		return;
	}
	
	curl_easy_cleanup(pstCurl);
}

const char* CLib_Curl::GetError()const
{
	return curl_easy_strerror(m_curlCode);
}

#ifndef _FTPINTERFACE_H_
#define _FTPINTERFACE_H_

#include "LibCurl.h"

using std::string;

typedef enum
{
    FTP_Work                    =0x00, //工作
    FTP_Free                    =0x01, //退出
}FTP_Run_Status_e;

typedef enum
{
    UnKnown_Ftp_Mode            = -1,
	Ftp_File_Upload             = 0x00, //文件上傳
	Ftp_Dir_Upload              = 0x00, //目錄上傳
    Ftp_File_Download           = 0x01, //文件下載
    Ftp_Dir_Download            = 0x01, //目錄下載
}FTP_Operat_Mode_e;

typedef enum
{
    Ftp_Local_err                   =-1,   //ftp內部異常,不以這個爲結束標準
    
    Ftp_Ok                          =0x00, //成功
    Ftp_LocalPath_Fail              =0x01, //終端本地路徑異常
    Ftp_RemotePath_Fail             =0x02, //遠程服務路徑異常
    Ftp_Disk_SpaceHungry            =0x03, //設備磁盤空間不足
    Ftp_UnKnown_WorkMode            =0x04, //未知的ftp工作模式
    Ftp_Connect_Fail                =0x05, //連接失敗
    Ftp_Login_Denied                =0x06, //登錄失敗
    Ftp_Memory_Fail                 =0x07, //內存分配請求失敗
    Ftp_GetFile_Fail                =0x08, //獲取文件錯誤
    Ftp_Service_Anomaly             =0x09, //ftp服務器異常
    Ftp_Url_Error                   =0x0A, //ftp遠程地址不正確

    Ftp_Unkown_error                =0xFF, //ftp未知錯誤
}FTP_Code_e;

typedef struct
{
    string strUrl;
    string strUsrePass;
}FTP_Remote_Usre_s;

typedef struct
{
    unsigned long u32Second; //單位秒
    unsigned long u32Size; //單位字節
}FTP_Transfer_Contrl_s;

class FtpServe:public CLib_Curl
{
public:
    FtpServe(FTP_Operat_Mode_e eMode, FTP_Remote_Usre_s stRemote, string strLocalPath, int s32TimeOut=10, FTP_Transfer_Contrl_s stTraCrl=m_sstTraCrl);
    ~FtpServe();
    void Ftp_StartServe();
    FTP_Code_e Ftp_GetCode(void);
    FTP_Run_Status_e Ftp_GetRunStatus(void);
public:
 
private:
    void* Ftp_ServeThread(void *pParm);
    FTP_Code_e Ftp_Convert_CurlCode(void);
    FTP_Code_e Ftp_Download(FTP_Operat_Mode_e eMode);
    FTP_Code_e Ftp_FileDownload(FTP_Operat_Mode_e eMode);
    FTP_Code_e Ftp_CheckPathValid(FTP_Operat_Mode_e eMode, const char *pInRemotePath, const char *pInLocalPath, char *pOutDirPath, int s32Size);
	unsigned int Ftp_CheckDiskSpace(const char *pPath);
	unsigned int Ftp_AvailableDisk(const char * pcDir) const;
    unsigned int Ftp_GetRemoteFileSize(void);
	static size_t Get_ContentLength(void *ptr, size_t size, size_t nmemb, void *stream);
	static size_t WriteFile_Func(void *ptr, size_t size, size_t nmemb, void *stream);
    
private:
    THREAD_STATUS_S	m_stFtpThread_status;

    CURL	*m_pCurl;
    FTP_Code_e m_eFtpCode;
    FTP_Operat_Mode_e m_eWorkMode;
    FTP_Remote_Usre_s m_stRemoteUser;
    FTP_Transfer_Contrl_s m_stTraCrl; //傳輸控制(單位時間低於傳輸字節數則退出)
    static const FTP_Transfer_Contrl_s m_sstTraCrl;
    string m_strDevLocalPath; //主機本地路徑
    int m_s32Timeout; //連接超時時間
};

#endif


/************************************************************
*FileName: FtpInterface.cpp
*Date:     2019.07.13
*Author:   qiuhui
*Version:  V1.0
*Description:基於curl庫封裝的ftp接口
*Others:TODO:上傳和目錄下載未完善
*History:   
***********************************************************/
#include "FtpInterface.h"

const FTP_Transfer_Contrl_s FtpServe::m_sstTraCrl = {30, 5};

FtpServe::FtpServe(FTP_Operat_Mode_e eMode,FTP_Remote_Usre_s stRemote,string strLocalPath,\
					int s32TimeOut,FTP_Transfer_Contrl_s stTraCrl)
					:m_eWorkMode(eMode)
					,m_stRemoteUser(stRemote)
					,m_strDevLocalPath(strLocalPath)
					,m_s32Timeout(s32TimeOut)
					,m_stTraCrl(stTraCrl)
{
	/* 初始化curl */
	m_pCurl = Init_CurlHandle();
	m_eFtpCode = Ftp_Ok;
	memset(&m_stFtpThread_status, 0, sizeof(m_stFtpThread_status));
}

FtpServe::~FtpServe(void)
{
	/* 銷燬 */
	Clean_CurlHandle(m_pCurl);
}

void* FtpServe::Ftp_ServeThread(void *pParm)
{
	QH_Debug("%s start,pthread_id:%u\r\n",m_stFtpThread_status.ThreadName, m_stFtpThread_status.pid);
	//while(true == m_stFtpThread_status.bThreadStart)
	{
		if ((Ftp_File_Upload==m_eWorkMode) || (Ftp_Dir_Upload==m_eWorkMode))
		{
			QH_Debug("FtpServe workMode Download:%d\r\n",m_eWorkMode);
		}
		else if ((Ftp_File_Download==m_eWorkMode) || (Ftp_Dir_Download==m_eWorkMode))
		{
			QH_Debug("FtpServe workMode Upload:%d\r\n",m_eWorkMode);
			m_eFtpCode = Ftp_Download(m_eWorkMode);
		}
		else
		{
			m_eFtpCode = Ftp_UnKnown_WorkMode;
			QH_Debug("FtpServe workMode Fail:%d\r\n",m_eWorkMode);
		}

		msleep(500);
	}

	m_stFtpThread_status.bThreadStart = false;

	QH_Debug("%s exit\r\n", m_stFtpThread_status.ThreadName);
	pthread_exit(NULL);
}

void FtpServe::Ftp_StartServe()
{
	if(false == m_stFtpThread_status.bThreadStart)
	{
		m_stFtpThread_status.bThreadStart = true;
		m_stFtpThread_status.ThreadName = "FtpServe_thread";

		if(0 == pthread_create(&m_stFtpThread_status.pid, NULL, (void*(*)(void*))&FtpServe::Ftp_ServeThread, this))
		{
			pthread_detach(m_stFtpThread_status.pid);
		}
		else
		{
			m_stFtpThread_status.bThreadStart = false;
		}
		
		msleep(100);
	}
}

FTP_Code_e FtpServe::Ftp_Download(FTP_Operat_Mode_e eMode)
{
	if (Ftp_File_Download == eMode)
	{
		return Ftp_FileDownload(eMode);
	}
	else if (Ftp_Dir_Download == eMode)
	{
		//TODO
	}
}

FTP_Code_e FtpServe::Ftp_FileDownload(FTP_Operat_Mode_e eMode)
{
	curl_off_t l_LocalFileLen = -1;
	FTP_Code_e l_eCode = Ftp_Ok;
	FILE *l_pFp = NULL;
	struct stat l_stfile_info;
	char l_s8DirPath[256] = {0};
	unsigned long l_u32FileSize = 0;
	unsigned long l_u32DiskSpace = 0;
	bool l_bFlag = false;
	
	memset(l_s8DirPath, 0, sizeof(l_s8DirPath));
	l_eCode = Ftp_CheckPathValid(eMode, m_stRemoteUser.strUrl.c_str(),  m_strDevLocalPath.c_str(), l_s8DirPath, sizeof(l_s8DirPath));
	if (Ftp_Ok != l_eCode)
	{
		QH_Debug("Path Check error:%d\r\n", l_eCode);
		return l_eCode;
	}

	/* 獲取本地文件大小信息 */
    if(stat(m_strDevLocalPath.c_str(), &l_stfile_info) == 0)
    {
        l_LocalFileLen = l_stfile_info.st_size; 
        l_bFlag = true;
    }
	
	/* 檢測目錄空間大小 */
	l_u32DiskSpace = Ftp_CheckDiskSpace(l_s8DirPath);
	l_u32FileSize = Ftp_GetRemoteFileSize();
	if (l_u32FileSize >= l_u32DiskSpace)
	{
		QH_Debug("Disk Space Hungry!!!\r\n");
		return Ftp_Disk_SpaceHungry;
	}

	/* 追加方式打開文件,實現斷點續傳 */
    l_pFp = fopen(m_strDevLocalPath.c_str(), "ab+");
    if (NULL == l_pFp)
	{
		QH_Debug("open:%s Failed,Error message:%s\r\n",m_strDevLocalPath.c_str(), strerror(errno));
        return Ftp_LocalPath_Fail;
    }

	/* 開始下載 */
	Set_URL(m_pCurl, m_stRemoteUser.strUrl.c_str());
	Set_UserPwd(m_pCurl, m_stRemoteUser.strUsrePass.c_str());

	Set_ConnectTimeout(m_pCurl, m_s32Timeout);

	/* 沒用到http方式,頭函數暫時不設置,注意回調函數要麼靜態,不要調用非靜態成員函數 */
	//l_u32FileSize = 0;
	//Set_HeaderFun(m_pCurl, &l_u32FileSize, (HeaderFun_Curl_t)FtpServe::Get_ContentLength);
	
	/* 設置斷點續傳 */
	Set_ResumeFromLarge(m_pCurl, l_bFlag==true?l_LocalFileLen:0);
	Set_WriteFun(m_pCurl, l_pFp, (HeaderFun_Curl_t)&FtpServe::WriteFile_Func);
	Set_TransferSpeed(m_pCurl, m_stTraCrl.u32Second, m_stTraCrl.u32Size);
	Set_ProgressBar(m_pCurl, false);
	Set_DebugInfo(m_pCurl, true);
	
	if (true == Perform_CurlHandle(m_pCurl))
	{
		fclose(l_pFp);
		return Ftp_Ok;
	}
	else
	{
		QH_Debug("File Download Failed,error:%s\r\n",GetError());
		fclose(l_pFp);
		return Ftp_Convert_CurlCode();
	}
}

unsigned int FtpServe::Ftp_GetRemoteFileSize(void)
{
	CURL* l_Curl;
	CURLcode res;
	unsigned long l_u32FileSize = 0;
	bool l_bRet = false;

	l_Curl = Init_CurlHandle();
	if (l_Curl)
	{
		Set_URL(l_Curl, m_stRemoteUser.strUrl.c_str());
		Set_UserPwd(l_Curl, m_stRemoteUser.strUsrePass.c_str());
		
		/* 連接超時設置 */
    	Set_ConnectTimeout(l_Curl, m_s32Timeout);
		Set_NoBody(l_Curl, true);
		Set_DebugInfo(l_Curl, true);

		if (true == Perform_CurlHandle(l_Curl)) 
		{
			double l_Size = 0.0;
			l_bRet = CurlInfo_ContentLength(l_Curl, &l_Size);//第二個參數必須爲(double*)否則會段錯誤
			if ((true==l_bRet) && (l_Size>=0))
			{
				l_u32FileSize = (unsigned long)l_Size;
				QH_Debug("Url:%s size:%ld[%0.0f]bytes\r\n",m_stRemoteUser.strUrl.c_str(), l_u32FileSize, l_Size);
			}
			else
			{
				QH_Debug("CurlInfo_ContentLength Failed,error:%s\r\n",GetError());
			}
	    }
		else
		{
			Ftp_Convert_CurlCode();
			QH_Debug("Get Remote File size Failed curlCode:%d,%s\r\n",m_curlCode,GetError());
		}
		
		Clean_CurlHandle(l_Curl);
	}
	
	return l_u32FileSize;
}

FTP_Code_e FtpServe::Ftp_CheckPathValid(FTP_Operat_Mode_e eMode, const char *pInRemotePath, const char *pInLocalPath, char *pOutDirPath, int s32Size)
{
	if (Ftp_File_Download == eMode)
	{
		if (('/'==pInRemotePath[strlen(pInRemotePath)-1]) || (NULL==pInRemotePath))
		{
			return Ftp_RemotePath_Fail;
		}

		if (('/'==pInLocalPath[strlen(pInLocalPath)-1]) || (NULL==pInLocalPath))
		{
			return Ftp_LocalPath_Fail;
		}

		if (NULL != pOutDirPath)
		{
			char *l_pAddr = NULL;
			if (NULL != (l_pAddr=_Strrstr((char *)pInLocalPath, (char *)"/")))
			{
				char l_s32MaxLen = (l_pAddr-pInLocalPath+1)>=s32Size?s32Size-1:(l_pAddr-pInLocalPath+1);
				memcpy(pOutDirPath, pInLocalPath, l_s32MaxLen);
			}
		}
	}
	else if (Ftp_Dir_Download == eMode)
	{
		if (('/'!=pInRemotePath[strlen(pInRemotePath)-1]) || (NULL==pInRemotePath))
		{
			return Ftp_RemotePath_Fail;
		}

		if (('/'!=pInLocalPath[strlen(pInLocalPath)-1]) || (NULL==pInLocalPath))
		{
			return Ftp_LocalPath_Fail;
		}

		if (NULL != pOutDirPath)
		{
			snprintf(pOutDirPath, s32Size, "%s", pInLocalPath);
			QH_Debug("Out Dirpath:%s\r\n", pOutDirPath);
		}
	}

	if (0 != access(pOutDirPath, F_OK))
	{
		if (0 > _MakeDirs(pOutDirPath))
		{
			QH_Debug("Creat Dir Error:%s\r\n", pOutDirPath);
			return Ftp_LocalPath_Fail;
		}
	}
	
	return Ftp_Ok;
}

unsigned int FtpServe::Ftp_AvailableDisk(const char *ps8Dir) const
{
	if(NULL == ps8Dir)
		return 0;
	struct statfs diskInfo;
	unsigned int blocksize = 0;       //每個block裏包含的字節數  
	unsigned int availableDisk  = 0;  //可用空間大小
	int iRet = -1;
	iRet = statfs(ps8Dir, &diskInfo);
	if(0 == iRet)
	{
		blocksize = diskInfo.f_bsize; 
		availableDisk = diskInfo.f_bavail * blocksize;//(byte)
	}

	QH_Debug("Current Dir Path:%s,available:%u\r\n", ps8Dir, availableDisk);
	return availableDisk;
}

unsigned int FtpServe::Ftp_CheckDiskSpace(const char *pPath)
{
	unsigned int l_u32Ret = 0;
	unsigned int i = 0;
	char l_s8pDirName[2][20]={"/data/", "/var/"};

	if (NULL == pPath)
	{
		l_u32Ret = 0;
		return l_u32Ret;
	}

	for (i=0; i<sizeof(l_s8pDirName)/sizeof(l_s8pDirName[0]); i++)
	{
		if (NULL != strstr(pPath, l_s8pDirName[i]))
		{
			break;
		}
	}

	if (i >= sizeof(l_s8pDirName)/sizeof(l_s8pDirName[0]))
	{
		l_u32Ret = 0;
		return l_u32Ret;
	}

	return Ftp_AvailableDisk(l_s8pDirName[i]);
}

FTP_Code_e FtpServe::Ftp_GetCode(void)
{
	return m_eFtpCode;
}

FTP_Code_e FtpServe::Ftp_Convert_CurlCode(void)
{
	switch (m_curlCode)
	{
		case CURLE_OK:	//成功
			m_eFtpCode = Ftp_Ok;
			break;

		case CURLE_OPERATION_TIMEDOUT:
		case CURLE_COULDNT_CONNECT:	//連接失敗
			m_eFtpCode = Ftp_Connect_Fail;
			break;
		
		case CURLE_LOGIN_DENIED:	//登錄失敗
			m_eFtpCode = Ftp_Login_Denied;
			break;

		case CURLE_REMOTE_ACCESS_DENIED: 
		case CURLE_FTP_ACCEPT_FAILED:
		case CURLE_FTP_WEIRD_PASV_REPLY:
		case CURLE_FTP_WEIRD_227_FORMAT:
			m_eFtpCode = Ftp_Service_Anomaly; //ftp服務器異常(暫時這樣,不一定是服務器異常,還可以細分)
			break;

		case CURLE_PARTIAL_FILE:
		case CURLE_WRITE_ERROR:
		case CURLE_BAD_DOWNLOAD_RESUME:
		case CURLE_RECV_ERROR:
		case CURLE_TFTP_NOTFOUND:
		case CURLE_REMOTE_FILE_NOT_FOUND:
			m_eFtpCode = Ftp_GetFile_Fail; //ftp獲取文件錯誤(暫時這樣,不一定是獲取文件錯誤,還可以細分)
			break;

		case CURLE_OUT_OF_MEMORY:
			m_eFtpCode = Ftp_Memory_Fail; //內存分配請求失敗
			break;
			
		case CURLE_URL_MALFORMAT:
			m_eFtpCode = Ftp_Url_Error; //網址的格式不正確
			break;
			
		default :
			m_eFtpCode = Ftp_Unkown_error; //未知錯誤
			break;
	}
	
	return m_eFtpCode;
}

FTP_Run_Status_e FtpServe::Ftp_GetRunStatus(void)
{
	if (true == m_stFtpThread_status.bThreadStart)
	{
		return FTP_Work;
	}
	else
	{
		return FTP_Free;
	}
}

/* 解析頭部長度 Content-Length */
size_t FtpServe::Get_ContentLength(void *ptr, size_t size, size_t nmemb, void *stream)
{
    int l_s32Ret;
    long l_s32len = 0;
    l_s32Ret = sscanf((const char*)ptr, "Content-Length: %ld\n", &l_s32len);
    if (l_s32Ret) /* Microsoft: we don't read the specs */
    {
    	*((unsigned long *) stream) = l_s32len;
		QH_Debug("%s,%lu\r\n", ptr, *((unsigned long *) stream));
    }
	
    return size * nmemb;
}

/* 將接收數據寫入FIFE* */
size_t FtpServe:: WriteFile_Func(void *ptr, size_t size, size_t nmemb, void *stream)
{
    return fwrite(ptr, size, nmemb, (FILE*)stream);
}



#include "FtpInterface.h"
int main(int argc,char** argv)
{
	FTP_Remote_Usre_s l_stUsrePasswd;
	FTP_Transfer_Contrl_s l_stTraCrl;
	l_stUsrePasswd.strUrl = "ftp://ip:port/filepath";
	l_stUsrePasswd.strUsrePass = "xxxxxxx";
	FtpServe l_FtpServe(Ftp_File_Download, l_stUsrePasswd, (char *)"/var/test1");
	l_FtpServe.Ftp_StartServe();

	l_stUsrePasswd.strUrl = "ftp://ip:port/filepath";
	FtpServe l_FtpServe11(Ftp_File_Download, l_stUsrePasswd, (char *)"/var/test2");
	l_FtpServe11.Ftp_StartServe();

	l_stUsrePasswd.strUrl = "ftp://ip:port/filepath";
	FtpServe l_FtpServe22(Ftp_File_Download, l_stUsrePasswd, (char *)"/var/test3");
	l_FtpServe22.Ftp_StartServe();

	l_stTraCrl.u32Second = 10;
	l_stTraCrl.u32Size = 20;
	l_stUsrePasswd.strUrl = "ftp://ip:port/filepath";
	FtpServe l_FtpServe33(Ftp_File_Download, l_stUsrePasswd, (char *)"/var/test4",20, l_stTraCrl);
	l_FtpServe33.Ftp_StartServe();

	l_stUsrePasswd.strUrl = "ftp://ip:port/filepath";
	FtpServe l_FtpServe44(Ftp_File_Download, l_stUsrePasswd, (char *)"/var/test5", 20, l_stTraCrl);
	l_FtpServe44.Ftp_StartServe();

	while ((FTP_Work==l_FtpServe.Ftp_GetRunStatus())\
		||(FTP_Work==l_FtpServe11.Ftp_GetRunStatus())
		||(FTP_Work==l_FtpServe22.Ftp_GetRunStatus())
		||(FTP_Work==l_FtpServe33.Ftp_GetRunStatus())
		||(FTP_Work==l_FtpServe44.Ftp_GetRunStatus()))
	{
		msleep(3000);
		QH_Debug("Wait:%dsecond\r\n", l_cout+=3);
	}
	QH_Debug("result:%d\r\n", l_FtpServe.Ftp_GetCode());
	QH_Debug("result:%d\r\n", l_FtpServe11.Ftp_GetCode());
	QH_Debug("result:%d\r\n", l_FtpServe22.Ftp_GetCode());
	QH_Debug("result:%d\r\n", l_FtpServe33.Ftp_GetCode());
	QH_Debug("result:%d\r\n", l_FtpServe44.Ftp_GetCode());
}

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章