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;
}
libcurl断点下载的更多相关文章
- libcurl断点下载遇到的问题
最近游戏把资源(图片.配置.lua)的加载.更新全部改了 ,加载其实还好,就是不走之前的zip解压方式. 以前的大体流程: 下载 –> 启动 –> 解压 –> 更新 –> ...
- 使用libCurl实现断点下载
关键部分代码如下: #include "curl.h" #pragma comment(lib, "libcurl.lib") size_t CROS_Down ...
- Java实现多线程断点下载(下载过程中可以暂停)
线程可以理解为下载的通道,一个线程就是一个文件的下载通道,多线程也就是同时开启好几个下载通道.当服务器提供下载服务时,使用下载者是共享带宽的,在优先级相同的情况下,总服务器会对总下载线程进行平均分配. ...
- 安卓(android)之实现断点下载功能
一.建立实体类 1.文件实体类 package com.example.zjw.myapplication.dao; import java.io.Serializable; /** * 预下载文件实 ...
- iOS 大文件断点下载
iOS 在下载大文件的时候,可能会因为网络或者人为等原因,使得下载中断,那么如何能够进行断点下载呢? // resumeData的文件路径 #define XMGResumeDataFile [[NS ...
- 【Java EE 学习 22 下】【单线程下载】【单线程断点下载】【多线程下载】
一.文件下载简述 1.使用浏览器从网页上下载文件,Servlet需要增加一些响应头信息 (1)response.setContentType("application/force-downl ...
- IOS 断点下载
// // ViewController.m // UI4_断点下载 // // Created by qianfeng on 15/8/19. // Copyright (c) 2015年 ZBC. ...
- .net网站的文件上传读取进度条和断点下载
文件上传到服务器时的进度读取 //调整上传配置 AdapterInfo(info); UpfileResult result = new UpfileResult(); try { //直接使用req ...
- iOS开发——网络篇——NSURLSession,下载、上传代理方法,利用NSURLSession断点下载,AFN基本使用,网络检测,NSURLConnection补充
一.NSURLConnection补充 前面提到的NSURLConnection有些知识点需要补充 NSURLConnectionDataDelegate的代理方法有一下几个 - (void)conn ...
随机推荐
- 电脑升级完Xcode8后 注释快捷键无效的问题
1.部分电脑升级完Xcode8 后直接重启电脑就可以使用Command +/ 快捷键注释代码, 2.如果上述方法没有效果,可以在终端输入sudo /usr/libexec/xpccachectl 然 ...
- secureCRT简单上传、下载文件记录
secureCRT简单上传.下载文件记录: 1)sz下载 -y 覆盖 2)rz上传 -y 覆盖 3)以上两个命令属于安装时包含在“Dial-up Networking Support"组中 ...
- 2014年度辛星css教程夏季版第二节
第一节我们简介了一下CSS的工作流程,我相信读者会有一个大体的认识,那么接下来我们将会深入的研究一下CSS的细节问题,这些问题的涉及将会使我们的工作更加完善. *************注释***** ...
- 制作精灵(UI Sprite)
怎样判断是否应该使用精灵 在一套UI中,精灵是一种非常常见的元件.当制作UI时,如果需要显示一张图片,需要先判断这个图片是否应该制作到图集里去,然后用精灵的方式去使用它,一般来说,可以遵循以下规律. ...
- 用python实现k近邻算法
用python写程序真的好舒服. code: import numpy as np def read_data(filename): '''读取文本数据,格式:特征1 特征2 -- 类别''' f=o ...
- C# 启动进程和杀死进程
/// <summary> /// 杀死进程 /// </summary> private void KillProcesses() { var cfn = GetAppset ...
- sqlserver分页;mysql分页;orcale分页 的sql 查询语句
一,sqlserver分页: )) ID FROM 表名 AS 表名1_1 ORDER BY ID)) ORDER BY ID; 二:mysql分页 )*每页显示的数据条数,当前页码 * 每页显示的数 ...
- shell 练习
shell 练习 iii= ] do iii=$[$iii+] echo -n "$iii " done iii= ] do iii=$[$iii+] echo -n " ...
- 事件——《JS高级程序设计》
一. 事件流 1. 事件流描述的是从页面中接收事件的顺序 2. 事件冒泡(event bubble):事件从开始时由最具体的元素(就是嵌套最深的那个节点)开始,逐级向上传播到较为不具体的节点(就是Do ...
- HDU4535+公式
错排公式. 用64位! /* */ #include<stdio.h> #include<string.h> #include<stdlib.h> #include ...