使用libCurl实现断点下载
关键部分代码如下:
#include "curl.h"
#pragma comment(lib, "libcurl.lib")
size_t CROS_DownloadDlg::getContentLengthFunc(void * ptr, size_t size, size_t nmemb, void * stream)
{
LONGLONG len = 0;
int r = sscanf((const char *)ptr, "Content-Length:%I64d\n",&len);
if(r)
*((LONGLONG *) stream) = len;
return size * nmemb;
}
//根据URL获取下载文件大小
LONGLONG CROS_DownloadDlg::getDownloadFileSize(const char* url)
{
double lensize = 0.0;
for(int iTry = 0 ; iTry < 3 ; iTry ++)//由于curl_easy_perform可能会有偶发性的CURLE_WRITE_ERROR错误,所以添加重试机制
{
CURL *handle = curl_easy_init();
curl_easy_setopt(handle, CURLOPT_URL, url);
curl_easy_setopt(handle, CURLOPT_HEADER, 1);
curl_easy_setopt(handle, CURLOPT_FOLLOWLOCATION, 1);
curl_easy_setopt(handle, CURLOPT_NOBODY, 1);
CURLcode res = curl_easy_perform(handle), resGetInfo = CURLE_OK;
if (res == CURLE_OK) {
resGetInfo = curl_easy_getinfo(handle, CURLINFO_CONTENT_LENGTH_DOWNLOAD, &lensize);
if(CURLE_OK == resGetInfo){
curl_easy_cleanup(handle);
return (LONGLONG)lensize;
}
}
curl_easy_cleanup(handle);
Sleep(200);
}
return 0;
}
size_t CROS_DownloadDlg::downLoadPackage(void *ptr, size_t size, size_t nmemb, void *userdata)
{
if(!ptr || !userdata)
return 0;
return fwrite(ptr, size, nmemb, (FILE *)userdata);
}
int CROS_DownloadDlg::assetsManagerProgressFunc(void *ptr, double totalToDownload, double nowDownloaded, double totalToUpLoad, double nowUpLoaded)
{
if(m_bStop)
return -1;
if(totalToDownload > 0.0)
{
CROS_DownloadDlg* pDlg = (CROS_DownloadDlg*)ptr;
pDlg->m_lProcessSize = (LONGLONG)nowDownloaded;
pDlg->SendMessage(WM_DOWNLOADPROC_MSG, 1, 0);
}
return 0;
}
/*
0 设置总大小
1 设置当前下载
2 下载完成
3 用户停止下载,其他异常终止下载
4 网络问题引发的下载异常
5 设备断开连接
6 磁盘剩余空间不足
*/
UINT CROS_DownloadDlg::DownloadProc(LPVOID lpParam)
{
//////////////////////////////////////////////////////////////////////////使用CURL实现下载
string sURL = CStringConverter::Unicode2Ansi(strURL.GetString()), sSavePath = CStringConverter::Unicode2Ansi(strSavePath.GetString());
LONGLONG local_file_len = GetFileSize(strSavePath);
pDlg->m_lLocalFileCurSize = local_file_len;
curl_global_init(CURL_GLOBAL_DEFAULT);
LONGLONG remote_file_len = getDownloadFileSize(sURL.c_str());
if(!remote_file_len)
{
pDlg->SendMessage(WM_DOWNLOADPROC_MSG, 4, 0);//网络问题获取失败
return 0;
}
pDlg->m_lTotalSize = remote_file_len;
pDlg->SendMessage(WM_DOWNLOADPROC_MSG, 0, 0);
if(local_file_len == remote_file_len)
{
pDlg->SendMessage(WM_DOWNLOADPROC_MSG, 2, 0);
return 0;
}
//得到准确大小后应判断strSavePath空间是否足够先
if(remote_file_len >= (pDlg->m_ulDiskSpaceMax))
{
pDlg->SendMessage(WM_DOWNLOADPROC_MSG, 6, 0);
return 0;
}
FILE *fp = fopen(sSavePath.c_str(), "ab+");
if(!fp)
{
pDlg->SendMessage(WM_DOWNLOADPROC_MSG, 3, 0);
return 0;
}
LONGLONG filesize = 0;
m_pCurl = curl_easy_init();//curl初始化
CURLcode res;
curl_easy_setopt(m_pCurl, CURLOPT_URL, sURL.c_str());//设定curl的链接
curl_easy_setopt(m_pCurl, CURLOPT_CONNECTTIMEOUT,5);//设置连接超时,单位秒
curl_easy_setopt(m_pCurl, CURLOPT_HEADERFUNCTION,getContentLengthFunc);
curl_easy_setopt(m_pCurl, CURLOPT_HEADERDATA, &filesize);
curl_easy_setopt(m_pCurl, CURLOPT_RESUME_FROM_LARGE, local_file_len);//断点下载设置
curl_easy_setopt(m_pCurl, CURLOPT_WRITEFUNCTION, downLoadPackage);
curl_easy_setopt(m_pCurl, CURLOPT_WRITEDATA, fp);//设置将data写入到文件流fp中
curl_easy_setopt(m_pCurl, CURLOPT_FOLLOWLOCATION, 1L);//设置重定位URL,使用自动跳转,返回的头部中有Location(一般直接请求的url没找到),则继续请求Location对应的数据
curl_easy_setopt(m_pCurl, CURLOPT_MAXREDIRS,5);//查找次数,防止查找太深
curl_easy_setopt(m_pCurl, CURLOPT_NOPROGRESS, false);//设为false 下面才能设置进度响应函数
curl_easy_setopt(m_pCurl, CURLOPT_PROGRESSFUNCTION, assetsManagerProgressFunc);//进度响应函数
curl_easy_setopt(m_pCurl, CURLOPT_PROGRESSDATA, pDlg);//数据传输的对象
curl_easy_setopt(m_pCurl, CURLOPT_VERBOSE,1L);
res = curl_easy_perform(m_pCurl);
curl_easy_cleanup(m_pCurl);
curl_global_cleanup();
m_pCurl = NULL;
if (res != CURLE_OK)
{
fclose(fp);
if(res == CURLE_ABORTED_BY_CALLBACK)//点击停止下载
pDlg->SendMessage(WM_DOWNLOADPROC_MSG, 3, 0);
else if(res == CURLE_RECV_ERROR)//断网 /* 56 - failure in receiving network data */
pDlg->SendMessage(WM_DOWNLOADPROC_MSG, 4, 0);
else
pDlg->SendMessage(WM_DOWNLOADPROC_MSG, 3, 0);
return 0;
}
fclose(fp);
pDlg->SendMessage(WM_DOWNLOADPROC_MSG, 2, 0);
return 0;
}
void CROS_DownloadDlg::OnClickBtnStop()
{
if(m_pCurl){
curl_easy_pause(m_pCurl, CURLPAUSE_RECV);
if(IDYES == ShowMessage(IDS_DEF_ROS_SURE_TO_STOP, CiPhoneUtil::GetApplicationName(), SM_ICON_QUESTION|SM_YES_AND_NO)){
m_btnStop.EnableWindow(FALSE);
m_bStop = true;
return;
}
curl_easy_pause(m_pCurl, CURLPAUSE_RECV_CONT);
}
}
使用libCurl实现断点下载的更多相关文章
- libcurl断点下载遇到的问题
最近游戏把资源(图片.配置.lua)的加载.更新全部改了 ,加载其实还好,就是不走之前的zip解压方式. 以前的大体流程: 下载 –> 启动 –> 解压 –> 更新 –> ...
- libcurl断点下载
开发需要写了一个处理curl 下载的c++类,内含有多个静态方法和实例方法,写在这里留给有需求的同学 头文件 CURLHelper.h enum CURLHelperStateType { CURLH ...
- 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 ...
随机推荐
- js验证
验证短日期(2007-06-05) function strDateTime(str) { var r = str.match(/^(\d{1,4})(-|\/)(\d{1,2})\2(\d{1 ...
- JSON 与List转换类封装
json与list转换小结: import java.util.ArrayList; import java.util.List; import com.google.gson.Gson; impor ...
- spring定时任务的配置
定时任务配置分为三个步骤: 1.定义任务 2.任务执行策略配置 3.启动任务 1.定义任务 <!--要定时执行的方法--> <bean id="testTaskJob&qu ...
- cmd 连接到指定路径
cmd 刚刚打开的时候默认路径可能不是自己想要的路径的时候,如何转到自己希望的路径,方法如下: 1.首先敲下想存的硬盘符:D: 2.敲下 cd+文件路径: 总结:其实这次只是简单测试一下上传图 ...
- linux yum配置
yum源模版 vi /etc/yum.repos.d/xxx.repo [rhel-server]name=serverbaseurl=file:///media/disk/Serverenabled ...
- 0基础学习ios开发笔记第二天
C语言的基本结构 c语言的入口函数是main函数. main函数的返回值行业标准是int return 数字:返回值 每条语句最后以分号结尾 注释:行注释.块注释 int main(void) { / ...
- 漫话JavaScript与异步·第一话——异步:何处惹尘埃
自JavaScript诞生之日起,频繁与异步打交道便是这门语言的使命,并为此衍生出了许多设计和理念.因此,深入理解异步的概念对于前端工程师来说极为重要. 什么是异步? 程序是分"块" ...
- struts 模型驱动
情景: 有一个用来处理用户的UserAction 类, 该动作类实现了 ModelDriven 接口. 当用户触发UserAction 动作时, ModelDriven 拦截器将调用相关UserAct ...
- DAG模型——嵌套矩阵
有向无环图上的动态规划是学习动态规划的基础,很多问题都可以转化为DAG上的最长路.最短路或路径计数问题. 嵌套矩阵 有n个矩阵,每个矩阵可以用两个整数a,b描述,表示它的长和宽.矩阵X(a,b)可以嵌 ...
- Speak softly love
Speak softly love and hold me warm against your heart 柔声诉情,拥我在你暖暖的心上 I feel your words, the tender t ...