libcurl断点下载

开发需要写了一个处理curl 下载的c++类,内含有多个静态方法和实例方法,写在这里留给有需求的同学

头文件

CURLHelper.h

enum CURLHelperStateType
{
CURLHelper_START = ,
CURLHelper_PROGRESS = ,
CURLHelper_COMPLETE = ,
CURLHelper_UNKNOW =
}; class CURLHelper
{
public:
static std::string getHttpString(const char * url); static long getDownloadFileSize(const char *url); static long getLocalFileSize(const char *localpath); CURLHelper();
~CURLHelper(); void downloadFile(const char *url,const char *localpath); void downloadProgressCallback(double percent); long getTotalFileSize(); CURLHelperStateType getState(); double getPercent(); void doDownload();
private:
string m_url;
string m_local_path; double m_fileTotalSize;
// double m_currentFileSize; double m_percent; pthread_t *pDownloadThread; int reDownloadCount;
CURLHelperStateType m_currentState;
};
/**
* 获取服务器文件的字符 ,阻塞式
* @param url
* @return
*/
string CURLHelper::getHttpString(const char *url)
{
std::string str = "";
CURL *_curl = curl_easy_init();
if (! _curl)
{
CCLOG("can not init curl");
return str;
}
curl_easy_setopt(_curl, CURLOPT_URL, url);
curl_easy_setopt(_curl, CURLOPT_SSL_VERIFYPEER, 0L);
curl_easy_setopt(_curl, CURLOPT_WRITEFUNCTION, getCharCode);
curl_easy_setopt(_curl, CURLOPT_WRITEDATA, &str); CURLcode res = curl_easy_perform(_curl);
if (res != CURLE_OK)
{
CCLOG("can not get version file content, error code is %d", res);
curl_easy_cleanup(_curl);
return str;
}
curl_easy_cleanup(_curl);
return str;
}
/**
* 获取服务器上的文件物理大小
* @param url
* @return
*/
long CURLHelper::getDownloadFileSize(const char *url)
{
double downloadFileLenth = ;
CURL *handle = curl_easy_init();
curl_easy_setopt(handle, CURLOPT_URL, url);
curl_easy_setopt(handle, CURLOPT_HEADER, ); //只需要header头
curl_easy_setopt(handle, CURLOPT_NOBODY, ); //不需要body
if (curl_easy_perform(handle) == CURLE_OK)
{
curl_easy_getinfo(handle, CURLINFO_CONTENT_LENGTH_DOWNLOAD, &downloadFileLenth);
}
else
{
downloadFileLenth = -;
}
return downloadFileLenth;
}
/**
* 获取本地文件大小
* @param localpath
* @return
*/
long CURLHelper::getLocalFileSize(const char *localpath)
{
curl_off_t local_file_len = ;
struct stat file_info;
if(stat(localpath, &file_info) == )
{
local_file_len = file_info.st_size;
}
return local_file_len;
} /* 保存下载文件 */ size_t wirtefunc(void *ptr, size_t size, size_t nmemb, void *stream)
{
FILE *fp = (FILE*)stream;
size_t written = fwrite(ptr, size, nmemb, fp);
return written;
}
/* 下载回调的计算进度条的函数 */
static int progress_func(void *ptr, double totalToDownload, double nowDownloaded, double totalToUpLoad, double nowUpLoaded)
{
CURLHelper *helper = (CURLHelper*)ptr;
double curpercent = * nowDownloaded / totalToDownload; helper->downloadProgressCallback(curpercent);
return ;
} void CURLHelper::doDownload()
{
do
{
string tmpPath = m_local_path + ".tmp";
FILE *localFile = NULL; double m_currentTmpSize = CURLHelper::getLocalFileSize(tmpPath.c_str()); if (m_currentTmpSize > )
{
localFile = fopen(tmpPath.c_str(), "ab+");
CCLOG("断点下载模式");
}
else
{
localFile = fopen(tmpPath.c_str(), "wb+");
}
int cc = error_no();
if (!localFile)
{
break;
}
m_currentState = CURLHelper_PROGRESS;
CURL *curlhandle = curl_easy_init();
curl_easy_setopt(curlhandle, CURLOPT_URL, m_url.c_str()); //写函数回调
curl_easy_setopt(curlhandle, CURLOPT_WRITEDATA, localFile);
curl_easy_setopt(curlhandle, CURLOPT_WRITEFUNCTION, wirtefunc);
//断点下载
curl_easy_setopt(curlhandle, CURLOPT_RESUME_FROM_LARGE, m_currentTmpSize);
//下载进度回调
curl_easy_setopt(curlhandle, CURLOPT_NOPROGRESS, 0L);
curl_easy_setopt(curlhandle, CURLOPT_PROGRESSFUNCTION, progress_func);
curl_easy_setopt(curlhandle, CURLOPT_PROGRESSDATA, this); CURLcode res = curl_easy_perform(curlhandle);
fclose(localFile);
curl_easy_cleanup(curlhandle); if (res == CURLE_OK)
{
//文件改名
int result = rename(tmpPath.c_str(), m_local_path.c_str());
int e = error_no();
if (result == )
{
CCLOG("改名成功");
}
else
{
CCLOG("rename failed %d",e);
}
}
else
{
CCLOG("下载失败,CURLcode %d",res);
if (reDownloadCount < )
{
//直接删除缓存文件
int removeCode = remove(tmpPath.c_str());
CCLOG("下载失败,删除tmp文件,并重新下载 %d",removeCode);
reDownloadCount++;
m_currentState = CURLHelper_START;
doDownload();
return;
}
} }
while ();
m_currentState = CURLHelper_COMPLETE;
} CURLHelper::CURLHelper()
{
m_currentState = CURLHelper_UNKNOW;
pDownloadThread = NULL;
m_percent = ;
reDownloadCount = ;
} CURLHelper::~CURLHelper()
{
CCLOG("~CURLHelper");
if (pDownloadThread)
{
delete pDownloadThread;
}
}
long CURLHelper::getTotalFileSize()
{
return m_fileTotalSize;
}
CURLHelperStateType CURLHelper::getState()
{
return m_currentState;
} static void *thread_downloadFiles(void* data)
{
CURLHelper *helper = (CURLHelper*)data;
helper->doDownload();
return NULL;
} void CURLHelper::downloadFile(const char *url, const char *localpath)
{
m_url = url;
m_local_path = localpath;
m_fileTotalSize = CURLHelper::getDownloadFileSize(url);
m_percent = ;
//记录当前状态
m_currentState = CURLHelper_START;
//开启线程下载
pDownloadThread = new pthread_t();
pthread_create(&(*pDownloadThread), NULL, thread_downloadFiles, (void*)this);
}
void CURLHelper::downloadProgressCallback(double percent)
{
m_percent = percent;
}
double CURLHelper::getPercent()
{
return m_percent;
}
上一篇:GCD 深入理解:第二部分


下一篇:Nginx Install 记录