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

  • 3
    点赞
  • 20
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值