跳转到主内容
极星编程网:以代码为星,赴技术山海!

Qt/C++ 调用迅雷开放下载引擎(ThunderOpenSDK)下载数据资源

目录导读 前言 ThunderOpenSDK 简介 参考 xiaomi_Thunder_Cloud 示例 ThunderOpenSDK 下载问题 前言 在对以前老版本的exe执行程序进行研究学习的时候,发现以前的软件是使用的 ThunderOpenSDK 这个迅雷开放下载引擎进行的项目数据下载,于是在网上搜索一番找到了相关内容,但是不知道为什么了相关资料相当少,不过用是真的好用,于是仔细的研究了一下。

ThunderOpenSDK 简介 ThunderOpenSDK 是一个迅雷开放下载引擎的 SDK,允许开发者在自己的应用程序中集成迅雷的下载功能。

该 SDK 提供了丰富的接口,支持多种下载任务的管理,包括任务的创建、启动、停止、删除等操作。

此外,SDK 还支持设置下载速度限制、代理、用户代理等功能,以满足不同应用场景的需求。

出自: ThunderOpenSDK 使用教程 相关内容参考: 迅雷开放下载引擎(ThunderOpenSDK)使用指南 ThunderOpenSDK 使用教程 配置云平台ip和端口 云平台接口 GitHub: ThunderOpenSDK ThunderOpenSDK 不需要再进行编译,直接附加到项目中就能直接使用,甚至示例程序都写好了,只管调用。

GitHub示例中有 0.CurUseCommonLib , 360Jisu_Thunder_Cloud , liebao_Thunder_Cloud , xiaomi_Thunder_Cloud , XunleiDownload_Old 5个版本的示例, 可以根据需求任选一个

通过查看xldl.dll文件的属性信息和Github上的声明, 我都毫不怀疑这些库文件是不是是从某个软件上扒下来的。

参考 xiaomi_Thunder_Cloud 示例 以 xiaomi_Thunder_Cloud 迅雷云加速开发平台 版本示例;

打开 xldl.h 文件可以发现 xldl.dll 的接口和数据结构都已经声明好还有注释,只管调用: xldl.h:

#pragma once

// 所有结构体定义按1字节对齐 #pragma pack(push, 1) struct DownTaskParam { DownTaskParam() { memset(this, 0, sizeof(DownTaskParam)); nReserved1 = 5; bReserved = FALSE; DisableAutoRename = FALSE; IsOnlyOriginal = FALSE; IsResume = TRUE; } int nReserved; wchar_t szTaskUrl[2084]; // 任务URL wchar_t szRefUrl[2084]; // 引用页 wchar_t szCookies[4096]; // 浏览器cookie wchar_t szFilename[MAX_PATH]; // 下载保存文件名. wchar_t szReserved0[MAX_PATH]; wchar_t szSavePath[MAX_PATH]; // 文件保存目录 HWND hReserved; BOOL bReserved; wchar_t szReserved1[64]; wchar_t szReserved2[64]; BOOL IsOnlyOriginal; // 是否只从原始地址下载 UINT nReserved1; BOOL DisableAutoRename; // 禁止智能命名 BOOL IsResume; // 是否用续传 DWORD reserved[2048]; }; enum DOWN_TASK_STATUS { NOITEM = 0, TSC_ERROR, TSC_PAUSE, TSC_DOWNLOAD, TSC_COMPLETE, TSC_STARTPENDING, TSC_STOPPENDING }; enum TASK_ERROR_TYPE { TASK_ERROR_UNKNOWN = 0x00, // 未知错误 TASK_ERROR_DISK_CREATE = 0x01, // 创建文件失败 TASK_ERROR_DISK_WRITE = 0x02, // 写文件失败 TASK_ERROR_DISK_READ = 0x03, // 读文件失败 TASK_ERROR_DISK_RENAME = 0x04, // 重命名失败 TASK_ERROR_DISK_PIECEHASH = 0x05, // 文件片校验失败 TASK_ERROR_DISK_FILEHASH = 0x06, // 文件全文校验失败 TASK_ERROR_DISK_DELETE = 0x07, // 删除文件失败失败 TASK_ERROR_DOWN_INVALID = 0x10, // 无效的DOWN地址 TASK_ERROR_PROXY_AUTH_TYPE_UNKOWN = 0x20, // 代理类型未知 TASK_ERROR_PROXY_AUTH_TYPE_FAILED = 0x21, // 代理认证失败 TASK_ERROR_HTTPMGR_NOT_IP = 0x30, // http下载中无ip可用 TASK_ERROR_TIMEOUT = 0x40, // 任务超时 TASK_ERROR_CANCEL = 0x41, // 任务取消 TASK_ERROR_TP_CRASHED= 0x42, // MINITP崩溃 TASK_ERROR_ID_INVALID = 0x43, // TaskId 非法 }; struct DownTaskInfo { DownTaskInfo() { memset(this, 0, sizeof(DownTaskInfo)); stat = TSC_PAUSE; fail_code = TASK_ERROR_UNKNOWN; fPercent = 0; bIsOriginUsable = false; fHashPercent = 0; } DOWN_TASK_STATUS stat; TASK_ERROR_TYPE fail_code; wchar_t szFilename[MAX_PATH]; wchar_t szReserved0[MAX_PATH]; __int64 nTotalSize; // 该任务总大小(字节) __int64 nTotalDownload; // 下载有效字节数(可能存在回退的情况) float fPercent; // 下载进度 int nReserved0; int nSrcTotal; // 总资源数 int nSrcUsing; // 可用资源数 int nReserved1; int nReserved2; int nReserved3; int nReserved4; __int64 nReserved5; __int64 nDonationP2P; // p2p贡献字节数 __int64 nReserved6; __int64 nDonationOrgin; // 原始资源共享字节数 __int64 nDonationP2S; // 镜像资源共享字节数 __int64 nReserved7; __int64 nReserved8; int nSpeed; // 即时速度(字节/秒) int nSpeedP2S; // 即时速度(字节/秒) int nSpeedP2P; // 即时速度(字节/秒) bool bIsOriginUsable; // 原始资源是否有效 float fHashPercent; // 现不提供该值 int IsCreatingFile; // 是否正在创建文件 DWORD reserved[64]; }; enum DOWN_PROXY_TYPE { PROXY_TYPE_IE = 0, PROXY_TYPE_HTTP = 1, PROXY_TYPE_SOCK4 = 2, PROXY_TYPE_SOCK5 = 3, PROXY_TYPE_FTP = 4, PROXY_TYPE_UNKOWN = 255, }; enum DOWN_PROXY_AUTH_TYPE { PROXY_AUTH_NONE =0, PROXY_AUTH_AUTO, PROXY_AUTH_BASE64, PROXY_AUTH_NTLM, PROXY_AUTH_DEGEST, PROXY_AUTH_UNKOWN, }; struct DOWN_PROXY_INFO { BOOL bIEProxy; BOOL bProxy; DOWN_PROXY_TYPE stPType; DOWN_PROXY_AUTH_TYPE stAType; wchar_t szHost[2048]; INT32 nPort; wchar_t szUser[50]; wchar_t szPwd[50]; wchar_t szDomain[2048]; }; struct WSAPROTOCOL_INFOW;

#pragma pack(pop)

namespace DownEngine { extern "C" __declspec(dllimport) BOOL XL_Init(void); extern "C" __declspec(dllimport) BOOL XL_UnInit(void); extern "C" __declspec(dllimport) HANDLE XL_CreateTask(DownTaskParam &stParam); extern "C" __declspec(dllimport) BOOL XL_DeleteTask(HANDLE hTask); extern "C" __declspec(dllimport) BOOL XL_StartTask(HANDLE hTask); extern "C" __declspec(dllimport) BOOL XL_StopTask(HANDLE hTask); extern "C" __declspec(dllimport) BOOL XL_ForceStopTask(HANDLE hTask); extern "C" __declspec(dllimport) BOOL XL_QueryTaskInfo(HANDLE hTask, DownTaskInfo & stTaskInfo); //旧版接口,使用Ex接口替换 extern "C" __declspec(dllimport) BOOL XL_QueryTaskInfoEx(HANDLE hTask, DownTaskInfo & stTaskInfo); extern "C" __declspec(dllimport) BOOL XL_DelTempFile(DownTaskParam &stParam); extern "C" __declspec(dllimport) void XL_SetSpeedLimit(INT32 nKBps); extern "C" __declspec(dllimport) void XL_SetUploadSpeedLimit(INT32 nTcpKBps,INT32 nOtherKBps); extern "C" __declspec(dllimport) BOOL XL_SetProxy(DOWN_PROXY_INFO &stProxyInfo); extern "C" __declspec(dllimport) void XL_SetUserAgent(const wchar_t *pszUserAgent); extern "C" __declspec(dllimport) BOOL XL_ParseThunderPrivateUrl(const wchar_t *pszThunderUrl, wchar_t *normalUrlBuffer, INT32 bufferLen); extern "C" __declspec(dllimport) BOOL XL_GetFileSizeWithUrl(const wchar_t * lpURL, INT64& iFileSize); extern "C" __declspec(dllimport) BOOL XL_SetFileIdAndSize(HANDLE hTask, char szFileId[40], unsigned __int64 nFileSize); extern "C" __declspec(dllimport) BOOL XL_SetAdditionInfo( HANDLE task_id, WSAPROTOCOL_INFOW *sock_info, CHAR *http_resp_buf, LONG buf_len ); extern "C" __declspec(dllimport) HANDLE XL_CreateTaskByURL(const wchar_t *url, const wchar_t *path, const wchar_t *fileName, BOOL IsResume); extern "C" __declspec(dllimport) LONG XL_CreateTaskByThunder(wchar_t *pszUrl, wchar_t *pszFileName, wchar_t *pszReferUrl, wchar_t *pszCharSet, wchar_t *pszCookie); extern "C" __declspec(dllimport) LONG XL_CreateBTTaskByThunder(const wchar_t *pszPath); };

相关函数的具体说明,可以参考Github上的文档 这一版本没有调用的示例,但是没关系, liebao_Thunder_Cloud 这一版本有调用示例;

参考 thunderWrapper.h 文件中的 thunderWrapper类 通过 LoadLibrary 和 GetProcAddress 函数调用,使用 MSCV2017编译器 并添加

引用,建议添加:

#include

#include #include #pragma comment(lib,"Shlwapi")

初始化函数示例: 只需要简单修改init方法,修改xldl.dll的加载路径,其他基本不变;

bool init(PCWSTR pDllPath = L"xldl.dll")

{ assert(!m_hModule); WCHAR szModulePath[MAX_PATH] = { 0 }; GetModuleFileNameW(NULL, szModulePath, MAX_PATH); PathRemoveFileSpecW(szModulePath); // 拆分路径 新版使用PathCchRemoveFileSpec qDebug()<<"[szModulePath] "<"; throw L"can not load xldl.dll"; } _Init = (fn_Init) GetProcAddress(m_hModule, "XL_Init"); _UnInit = (fn_UnInit) GetProcAddress(m_hModule, "XL_UnInit"); _TaskCreate = (fn_TaskCreate) GetProcAddress(m_hModule, "XL_CreateTask"); _TaskDelete = (fn_TaskDelete) GetProcAddress(m_hModule, "XL_DeleteTask"); _TaskStart = (fn_TaskStart) GetProcAddress(m_hModule, "XL_StartTask"); _TaskPause = (fn_StopTask) GetProcAddress(m_hModule, "XL_StopTask"); _TaskForcePause = (fn_StopTask) GetProcAddress(m_hModule, "XL_ForceStopTask"); _TaskQuery = (fn_TaskQuery) GetProcAddress(m_hModule, "XL_QueryTaskInfo"); _TaskQueryEx = (fn_TaskQueryEx) GetProcAddress(m_hModule, "XL_QueryTaskInfoEx"); _LimitSpeed = (fn_LimitSpeed) GetProcAddress(m_hModule, "XL_SetSpeedLimit"); _LimitUploadSpeed = (fn_LimitUploadSpeed) GetProcAddress(m_hModule, "XL_SetUploadSpeedLimit"); _DelTempFile = (fn_DelTempFile) GetProcAddress(m_hModule, "XL_DelTempFile"); _SetProxy = (fn_SetProxy) GetProcAddress(m_hModule, "XL_SetProxy"); _SetUserAgent = (fn_SetUserAgent) GetProcAddress(m_hModule, "XL_SetUserAgent"); _GetFileSizeWithUrl = (fn_GetFileSizeWithUrl) GetProcAddress(m_hModule, "XL_GetFileSizeWithUrl"); _ParseThunderPrivateUrl = (fn_ParseThunderPrivateUrl) GetProcAddress(m_hModule, "XL_ParseThunderPrivateUrl"); _SetAdditionInfo = (fn_SetAdditionInfo) GetProcAddress(m_hModule, "XL_SetAdditionInfo"); _SetFileIdAndSize = (fn_SetFileIdAndSize) GetProcAddress(m_hModule, "XL_SetFileIdAndSize"); _CreateTaskByURL = (fn_CreateTaskByURL) GetProcAddress(m_hModule, "XL_CreateTaskByURL"); _CreateTaskByThunder = (fn_CreateTaskByThunder) GetProcAddress(m_hModule, "XL_CreateTaskByThunder"); _CreateBTTaskByThunder = (fn_CreateBTTaskByThunder) GetProcAddress(m_hModule, "XL_CreateBTTaskByThunder");

CHECKFUNC(_Init, false); return _Init() == TRUE; }

需要注意的是在不同版本中,所包含的方法函数也不一样,例如 liebao_Thunder_Cloud 版就没有 XL_CreateTaskByURL 函数方法, 实际线程调用: 继承QThread类,重写

void run() override;

方法,获取文件总大小,下载进度,下载有效字节数,即时速度,倒计时等信息,并通过信号槽控制下载的中断和退出。

void QThread_ThunderWrapper::run()

{ emit IsStart(true); bool ISuccessed=false; IsQuit=false; QString Error=""; try { qDebug()<<"QThread_ThunderWrapper Start!"; thunderWrapper=new Lib_ThunderWrapper(); bool ISuccessed=thunderWrapper->init(); if(!ISuccessed) throw QString("Lib_ThunderWrapper 初始化失败!"); else qDebug()<<"thunderWrapper->init : Successed!";

wchar_t * url=utf8_to_wchar(Urlpath.toStdString().c_str()); wchar_t * path=utf8_to_wchar(Filepath.toStdString().c_str()); wchar_t * fileName=utf8_to_wchar(Filename.toStdString().c_str());

if(!thunderWrapper->CreateTaskByURL(url,path,fileName,TRUE)) { thunderWrapper->unInit(); throw QString("taskCreate 失败!"); } else qDebug()<<"thunderWrapper->taskCreate : Successed!";

if(!thunderWrapper->taskStart()) { thunderWrapper->taskDelete(); thunderWrapper->unInit(); throw QString("taskStart 失败!"); } else qDebug()<<"thunderWrapper->taskStart : Successed!";

//! 1秒查询一次 msleep(1000); DownTaskInfo stTaskInfo; while (!IsQuit) { if(thunderWrapper->taskQueryEx(stTaskInfo)) { if(stTaskInfo.stat==TSC_ERROR) { emit Current_status("下载失败!",TSC_ERROR); throw QString("TSC_ERROR: fail_code:%1").arg(stTaskInfo.fail_code); } else if(stTaskInfo.stat==TSC_PAUSE) { emit Current_status("下载暂停!",TSC_PAUSE); } else if(stTaskInfo.stat==TSC_DOWNLOAD) { emit Current_status("正在下载...",TSC_PAUSE); emit Down_Speed(stTaskInfo.nSpeed); emit ProgressBar((int)stTaskInfo.fPercent*100); emit SendDownsize(stTaskInfo.nTotalDownload,stTaskInfo.nTotalSize); if(stTaskInfo.nSpeed>0) emit Time_Remaining((stTaskInfo.nTotalSize-stTaskInfo.nTotalDownload)/stTaskInfo.nSpeed); } else if(stTaskInfo.stat==TSC_COMPLETE) { ISuccessed=true; IsQuit=true; emit Current_status("下载完成",TSC_COMPLETE); emit Down_Speed(stTaskInfo.nSpeed); emit ProgressBar((int)stTaskInfo.fPercent*100); emit SendDownsize(stTaskInfo.nTotalDownload,stTaskInfo.nTotalSize); emit Time_Remaining(0); break; } else if(stTaskInfo.stat==TSC_STARTPENDING) { emit Current_status("等待下载!",TSC_STARTPENDING); } else if(stTaskInfo.stat==TSC_STOPPENDING) { emit Current_status("停止等待!",TSC_STARTPENDING); } // qDebug().noquote()<

} catch (QString error) { ISuccessed=false; Error="异常信息 :"+error; } catch (...) {} qDebug()<<"thunderWrapper unInit-->"; thunderWrapper->unInit(); //! 清除连接 delete thunderWrapper; thunderWrapper=nullptr; emit IsStart(true); }

如图所示: 下载在网上找到系统镜像文件时, ThunderOpenSDK 下载速度更快, 能稳定到9mb/s左右,而通过原生的 QNetworkReply 下载最高在5Mb/s左右。

ThunderOpenSDK 下载问题 ThunderOpenSDK无法下载包含重定向跳转的下载链接, 正当我打算整体改用 ThunderOpenSDK 下载时,我突然发现 ThunderOpenSDK 无法下载项目中的资源文件,换成其他网上找的资源文件又能正常下载, 测试多次发现 ThunderOpenSDK 只能下载直接指向下载资源的链接,

包含重定向跳转的下载链接下载不了!

无解,果断放弃,还是改用调用 Aria2 下载! 不过一般的下载 ThunderOpenSDK 库也完全够用了。

相关文章