一个基于WinHttp的轻量级的分片下载库介绍
作者:magictong
日期:2018/04/09
资源下载
https://download.csdn.net/download/magictong/10370195
主要目的
1、下载文件到内存。
2、下载分片Range文件(譬如下载某个资源文件的第100字节到第150字节的内容)。
3、不需要回调线程是UI线程(有消息循环)。
适用场景
1、小文件全量下载(注:暂未支持断点续传)。
2、分片文件下载(注:下载某个文件中的一段内容)。
3、支持https协议(仅支持只需要验证服务器端的情况)。
适用系统
受限于WinHttp的支持,本库需要Windows XP SP1以上或者Windows 2000 SP3以上才能使用。
头文件介绍
1、QMTINYDL::IQMTinyDLSink接口
使用类需要从QMTINYDL::IQMTinyDLSink接口进行继承,实现它的三个虚函数(OnTinyDLComplete,OnTinyDLProgress,OnTinyDLError),OnTinyDLComplete必须实现,其它两个可以按需要实现,这个接口主要用于下载完成,下载失败,下载出错,下载进度的回调,使用者只有通过此接口的回调感知下载库的工作进度。回调函数参数说明参考下面的注释。
//-------------------------------------------------------------------------
// 类名 : IQMTinyDLSink
// 功能 : QMTinyDL下载回调接口
// 附注 :使用IQMTinyDLMgr接口进行下载的类需要继承本接口
// -------------------------------------------------------------------------
class IQMTinyDLSink
{
public:
virtual ~IQMTinyDLSink() {}
//-------------------------------------------------------------------------
// 函数 :OnTinyDLComplete
// 功能 :下载结束回调(dwErr==0表示下载成功)
// 返回值 : virtualvoid
// 参数 : LONGlTaskID任务id
// 参数 : void*pBuffer如果是下载到内存需求,则指向该内存,如果是下载到文件,则指向(wchar*)文件路径
// 参数 : DWORDdwSize下载总长度
// 参数 : DWORDdwErr错误码
// 参数 : PVOIDpContext上下文参数
// 附注 :必须实现
//-------------------------------------------------------------------------
virtual void OnTinyDLComplete(LONG lTaskID, void* pBuffer, DWORD dwSize,DWORD dwErr, PVOID pContext) = 0;
//-------------------------------------------------------------------------
// 函数 :OnTinyDLProgress
// 功能 :下载进度回调
// 返回值 : virtualvoid
// 参数 : LONGlTaskID任务id
// 参数 : DWORDdwLen当前下载长度
// 参数 : DWORDdwTotalLen需要下载总长度
// 参数 : PVOIDpContext上下文参数
// 附注 :可选实现
//-------------------------------------------------------------------------
virtual void OnTinyDLProgress(LONG lTaskID, DWORD dwLen, DWORDdwTotalLen, PVOID pContext) {}
//-------------------------------------------------------------------------
// 函数 :OnTinyDLError
// 功能 :下载中途错误回调
// 返回值 : virtualvoid
// 参数 : LONGlTaskID任务id
// 参数 : DWORDdwErr错误码
// 参数 : PVOIDpContext上下文参数
// 附注 :可选实现
//-------------------------------------------------------------------------
virtual void OnTinyDLError(LONG lTaskID, DWORD dwErr, PVOID pContext) {}
};
//-------------------------------------------------------------------------
// 枚举名 : ERRORCODE
// 功能 :下载失败错误码
// 附注 :通过DWORD dwErr参数传递
//-------------------------------------------------------------------------
enum
{
ERRORCODE_NULL=0, //SUCCESS
ERRORCODE_NOMODIFIED = 1, // Nomodified . so no update
ERRORCODE_NETWORKFAILED = 2,
ERRORCODE_OPEN_HTTP = 3,
ERRORCODE_FILE_ERROR = 4,
ERRORCODE_USER_ABORT = 5,
ERRORCODE_FAILED = 6,
//
// 创建下载实例失败,申请buffer失败等
// add by magictong 2016/12/16 11:33:33
//
ERRORCODE_CREATE_HTTPDOWNLOAD_FAILED = 7,
ERRORCODE_NEWBUF_FAILED = 8,
ERRORCODE_STOP_HANDLE_NULL = 9,
ERRORCODE_NOT_SUPPORT_WINHTTP = 10,
};
2、QMTINYDL:: IQMTinyDLMgr
使用类进行下载请求前,需要先获得QMTINYDL:: IQMTinyDLMgr接口,该接口由4个启动方法,1个反注册接口,2个停止方法和1个代理设置接口组成。详细参数信息参考下面的对应注释。
//-------------------------------------------------------------------------
// 类名 : IQMTinyDLMgr
// 功能 : QMTinyDL外部使用接口
// 附注 :
// -------------------------------------------------------------------------
class IQMTinyDLMgr
{
public:
~IQMTinyDLMgr() {}
//-------------------------------------------------------------------------
// 函数 :CHTTPDownloadEx::StartTaskToBuf
// 功能 :下载到内存,需要设置大小
// 返回值 : DWORD任务id(当前进程唯一)
// 参数 :IQMTinyDLSink* pCallbackObj回调接口
// 参数 :LPCWSTR pUrl下载链接
// 参数 :DWORD64 dw64Size下载大小
// 参数 : PVOIDpContext上下文参数
// 附注 :注意:需要设置大小,内部需要提前分配内存
//-------------------------------------------------------------------------
virtual DWORD StartTaskToBuf(
IQMTinyDLSink* pCallbackObj,
LPCWSTR pUrl,
DWORD64 dw64Size,
PVOID pContext = NULL) = 0;
//-------------------------------------------------------------------------
// 函数 :CHTTPDownloadEx::StartRangeTaskToBuf
// 功能 :下载到内存,分片下载
// 返回值 : DWORD任务id(当前进程唯一)
// 参数 :IQMTinyDLSink* pCallbackObj回调接口
// 参数 :LPCWSTR pUrl下载链接
// 参数 :DWORD64 dw64Offset下载偏移(0开始)
// 参数 :DWORD64 dw64Size下载分片大小
// 参数 : PVOIDpContext上下文参数
// 附注 :如果启动失败,则返回0,否则返回任务ID
//-------------------------------------------------------------------------
virtual DWORD StartRangeTaskToBuf(
IQMTinyDLSink* pCallbackObj,
LPCWSTR pUrl,
DWORD64 dw64Offset,
DWORD64 dw64Size,
PVOID pContext = NULL) = 0;
//-------------------------------------------------------------------------
// 函数 :CHTTPDownloadEx::StartTaskRange
// 功能 :进行下载,下载到文件
// 返回值 : DWORD任务id(当前进程唯一)
// 参数 :IQMTinyDLSink* pCallbackObj回调接口
// 参数 :LPCWSTR pUrl下载链接
// 参数 :LPCWSTR lpFilePath下载到目标文件全路径
// 参数 : PVOIDpContext上下文参数
// 附注 :如果启动失败,则返回0,否则返回任务ID
//-------------------------------------------------------------------------
virtual DWORD StartTask(
IQMTinyDLSink* pCallbackObj,
LPCWSTR pUrl,
LPCWSTR lpFilePath,
PVOID pContext = NULL) = 0;
//-------------------------------------------------------------------------
// 函数 :CHTTPDownloadEx::StartRangeTask
// 功能 :进行分片下载
// 返回值 : DWORD任务id(当前进程唯一)
// 参数 :IQMTinyDLSink* pCallbackObj回调接口
// 参数 :LPCWSTR pUrl下载链接
// 参数 :LPCWSTR lpFilePath下载到目标文件全路径
// 参数 :DWORD64 dw64Offset下载偏移(0开始)
// 参数 :DWORD64 dw64Size下载分片大小
// 参数 : PVOIDpContext上下文参数
// 附注 :如果启动失败,则返回0,否则返回任务ID
//-------------------------------------------------------------------------
virtual DWORD StartRangeTask(
IQMTinyDLSink* pCallbackObj,
LPCWSTR pUrl,
LPCWSTR lpFilePath,
DWORD64 dw64Offset,
DWORD64 dw64Size,
PVOID pContext = NULL) = 0;
//-------------------------------------------------------------------------
// 函数 :StopTask
// 功能 :停止id为lTaskID的下载任务
// 返回值 : void
// 参数 : LONGlTaskID
// 附注 :
// -------------------------------------------------------------------------
virtual void StopTask(LONG lTaskID) = 0;
//-------------------------------------------------------------------------
// 函数 :StopAllTask
// 功能 :停掉所有的下载任务
// 返回值 : void
// 附注 :
//-------------------------------------------------------------------------
virtual void StopAllTask() = 0;
//-------------------------------------------------------------------------
// 函数 :SetProxy
// 功能 :设置代理信息
// 返回值 : virtualvoid
// 参数 :QMTINYDL::QMDLPROXYTYPE proxyType,
// 参数 : PCWSTRlpszAddress
// 参数 : USHORTusPort
// 参数 :LPCWSTR lpszUserName = NULL
// 参数 :LPCWSTR lpszPassword = NULL
// 参数 :LPCWSTR lpszDomain = NULL
// 附注 :如果不调用SetProxy,组件内部会自动处理管家代理
//-------------------------------------------------------------------------
virtual void SetProxy(
QMTINYDL::QMDLPROXYTYPE proxyType,
LPCWSTR lpszAddress,
USHORT usPort,
LPCWSTR lpszUserName = NULL,
LPCWSTR lpszPassword = NULL,
LPCWSTR lpszDomain = NULL) = 0;
//-------------------------------------------------------------------------
// 函数 :UnregisterCallback
// 功能 :反注册回调
// 返回值 : virtualBOOL
// 参数 :IQMTinyDLSink* pCallbackObj
// 附注 :
//-------------------------------------------------------------------------
virtual BOOL UnregisterCallback(IQMTinyDLSink* pCallbackObj) = 0;
};
3、头文件里面QMDLProxyInfo和QMDLPROXYTYPE定义是代理相关内容,按需使用即可,另外库内部初始化时会自动处理IE设置的代理,如果外部调用SetProxy方法手动设置代理,则使用手动设置的代理。
使用方法
1、实现QMTINYDL::IQMTinyDLSink接口,相关调用者自己按需实现即可。
2、获得QMTINYDL:: IQMTinyDLMgr接口,获取该接口有两个方法:
(1) 一种是直接使用QMTinyDL.dll(MD编译)的导出函数获取:
//
// Export原型如下
//
extern "C" IQMTinyDLMgr*__stdcall CreateQMTinyDLMgr();
extern "C" int __stdcallDestroyQMTinyDLMgr(IQMTinyDLMgr* p);
extern "C" unsigned int__stdcall GetQMTinyDLVer();
先使用CreateQMTinyDLMgr获得IQMTinyDLMgr接口,使用完之后调用DestroyQMTinyDLMgr释放。
(2) 另外一种方法是使用QMTINYDL库的辅助lib(QMTinyDLLib.lib:MD编译)来获取,节省寻找加载QMTinyDL.dll的操作。
使用该lib只需要引入IQMTinyDL.h头文件,使用里面的两个函数CreateQMTinyDLMgr和DestroyQMTinyDLMgr即可。
//-------------------------------------------------------------------------
// 函数 : CreateQMTinyDLMgr
// 功能 :创建IQMTinyDLMgr接口
// 返回值 : IQMTinyDLMgr*
// 附注 :
//-------------------------------------------------------------------------
extern "C" IQMTinyDLMgr*__stdcall CreateQMTinyDLMgr();
// -------------------------------------------------------------------------
// 函数 : DestroyQMTinyDLMgr
// 功能 :释放IQMTinyDLMgr接口
// 返回值 : int
// 参数 : IQMTinyDLMgr* p
// 附注 :
//-------------------------------------------------------------------------
extern "C" int __stdcall DestroyQMTinyDLMgr(IQMTinyDLMgr*p);
注意:在使用QMTINYDL:: IQMTinyDLMgr接口的Start*系列方法(譬如:StartRangeTask)时,传入了一个QMTINYDL::IQMTinyDLSink接口,在调用DestroyQMTinyDLMgr之前需要把该接口从库里面反注册,务必调用QMTINYDL:: IQMTinyDLMgr接口的UnregisterCallback方法将其反注册,否则如果实现QMTINYDL::IQMTinyDLSink接口的外部对象提前销毁,极易导致下载库Crash,这里没有使用引用计数来管理各个对象主要是基于简单轻便的考虑。
使用举例
1、头文件。
class CDeltaDlder
:public QMTINYDL::IQMTinyDLSink
,public DeltaTaskBase
{
public:
CDeltaDlder(void);
~CDeltaDlder(void);
……
// -------------------------------------------------------------------------
// IQMTinyDLSink
//
virtual void OnTinyDLComplete(LONG lTaskid, void* pBuffer, DWORD dwSize,DWORD dwErr, PVOID pContext);
virtual void OnTinyDLProgress(LONG lTaskID, DWORD dwLen, DWORDdwTotalLen, PVOID pContext) {}
virtual void OnTinyDLError(LONG lTaskID,DWORD dwErr, PVOID pContext) {}
……
private:
QMTINYDL::IQMTinyDLMgr* m_pHttpDlder;
……
};
2、实现文件
BOOL CDeltaDlder::Init()
{
……
BOOLbRet = FALSE;
if(!m_pHttpDlder)
{
m_pHttpDlder = QMTINYDL::CreateQMTinyDLMgr();
}
if(!m_pHttpDlder)
{
LOG_ERROR_PRINTF(_T("[%s]QMTINYDL::CreateQMTinyDLMgr Error"), __FUNCTIONW__);
bRet= FALSE;
}
else
{
bRet= TRUE;
}
returnbRet;
}
VOID CDeltaDlder::UnInit()
{
if (m_pHttpDlder)
{
LOG_COMMON_PRINTF(L"[%s] UnInit()", __FUNCTIONW__);
m_pHttpDlder->UnregisterCallback(this);
QMTINYDL::DestroyQMTinyDLMgr(m_pHttpDlder);
m_pHttpDlder = NULL;
}
}
void CDeltaDlder::OnTinyDLComplete(LONGlTaskid, void* pBuffer, DWORD dwSize, DWORD dwErr, PVOID pContext)
{
utils::CCriticalSection::Ownero(m_csDL);
BOOL bDoTry = FALSE;
if(QMTINYDL::ERRORCODE_NULL != dwErr && lTaskid) //
{
……
}
……
}
……
DWORD dwTaskId = m_pHttpDlder->StartRangeTask(this, m_strDldUrl,itr->strDldFileName, itr->dw64DldOffset, itr->dw64DldLength);
……
一个基于WinHttp的轻量级的分片下载库介绍相关推荐
- 一个基于EntityFrameworkCore+Lucene实现的全文搜索引擎库
一说到全文搜索,大家都可能会想到ES中间件,毕竟ES非常强大.对于复杂全文搜索场景ES非常好用,但是对于一些简单业务场景的,比如实现通过关键字检索文章,使用ES就显得比较重.今天就给大家推荐一个基于E ...
- pd.fjs分片下载的介绍2:分片下载demo
上一个章节,简要说了以下分片下载的几个特性.今天主要用示例说明一下pdf.js分片下载. 服务器环境: php7.2 nginx 1.14 ubuntu 18.04 测试浏览器:谷歌浏览器 70.0. ...
- PDF.js 分片下载的介绍2:分片下载demo
上一个章节,简要说了以下分片下载的几个特性.今天主要用示例说明一下pdf.js分片下载. 服务器环境: php7.2 nginx 1.14 ubuntu 18.04 测试浏览器:谷歌浏览器 70.0. ...
- 基于WPF的Metro风格的MehApp库介绍
基本情况 是一个基于WPF的,开源的Metro风格的第三方库. 官方介绍网站在这里https://mahapps.com/,其源码在GitHubhttps://github.com/MahApps/M ...
- php在线播放bt,yunBT:一个基于ThinkCMS的多用户BT离线下载程序,支持在线播放
说明:yunBT这个项目其实很早就有了,只是老没更新,现在作者基于ThinkCMS重做该程序,支持多用户注册下载,Magnet和HTTP下载.每个单独用户支持10个任务,默认下载文件最大为10GB,可 ...
- 一个基于BCH的付费电驴下载的设想
作者新浪微博:中本蒜-袁维 感觉不比ipfs和joystream差 刚刚吃饭,想到了一个付费下载的解决方案,可以把电驴和BCH结合在一起. 虽然目前有ipfs和joystream,但是前者似乎也 ...
- 一个基于JRTPLIB的轻量级RTSP客户端(myRTSPClient)——实现篇:(八)RTP音视频传输解析层之MPA传输格式...
一.MPEG RTP音频传输 相较H264的RTP传输格式,MPEGE音频传输格式则简单许多. 每一包MPEG音频RTP包都前缀一个4字节的Header,如下图(RFC2550) "MBZ& ...
- 一个基于JRTPLIB的轻量级RTSP客户端(myRTSPClient)——收流篇:(四)example代码解析...
--------------------更新2018.08.20------------------- 添加http_tunnel_example.cpp作为RtspOverHttp示例程序. --- ...
- bodhi linux 安装 ubuntu软件,Bodhi Linux 5.1.0 发布,基于Ubuntu的轻量级发行版
Bodhi Linux是基于Ubuntu的轻量级发行版,具有Moksha桌面环境.现在有很多Linux发行版.有些是独特的,但很多是重复的,可能没有存在的必要.由于使用了Moksha桌面环境,一个基于 ...
- 基于 Vue 的轻量级静态网站生成器 VuePress
Vue.js 的创始人尤雨溪大大在 twitter 上发布了一个全新的基于 Vue 的静态网站生成器-,这对于广大 Vue 爱好者来说无疑是一个好消息! 什么是VuePress VuePress由两部 ...
最新文章
- 求凸包(两遍扫描,求上下凸包的方法)
- Struts2数据封装
- mac matlab 中文乱码,MAC让Matlab编辑器显示中文的方法
- Android 系统(211)---Power键不亮屏分析方法
- springboot--多环境
- 移动硬盘提示数据错误循环冗余检查的文件恢复方案
- html火焰字效果,ps怎样制作燃烧的火焰字 巧用图层样式给字体增加火焰特效教程...
- Windows中texstudio的主题代码(持续更新)
- 计算机表格里的隐藏怎么弄出来怎么办,电脑表格隐藏不见了怎么办
- 关于接口幂等性问题的简单总结
- 7-35 英文字母的大小写转换
- Ubuntu16.04如何设置自动休眠时间
- 全球投资者聚焦阿里巴巴新零售:天猫力量定义商业未来
- 皮卡丘(pikachu)越权漏洞
- WindowsForm 入门
- 电报电话的原理和作用
- C#:使用Spire.xls写Excel数据
- ECshop文件结构说明
- 北京市普通公路配齐交通诱导屏
- 电梯调度问题模型分析及程序设计(一)
热门文章
- 魔兽按键精灵 V2.0(修正1)
- 计算机专业助我成长作文600,挫折助我成长作文(精选6篇)
- 生成1-100随机数并进行猜测
- 元宇宙地产演化史:从文本时代到区块链时代
- linux rm命令 安装,Linux rm 命令 command not found rm 命令详解 rm 命令未找到 rm 命令安装 - CommandNotFound ⚡️ 坑否...
- c++11新特性介绍
- 电商运营数据分析常用分析指标--概述及流量指标
- excel自动求和_excel自动求和你会吗?更改姓名自动算出总分,三个函数轻松搞定...
- AI机器学习面试常见问题与答案
- 2022-9-28 c高级的复习