• 最近闲的时候做了一个应用平台,既然是应用平台,肯定要用到下载,调用系统自带的winInet下载的话,速度非常不稳定,单线程,还没法续传,这时候迅雷下载SDK就非常适合了。

     

    申请地址:http://open.xunlei.com

    QQ截图20140627093855

    申请到SDK之后,你会得到一个压缩包

    QQ截图20140627094026

    Download文件夹内包含了迅雷的下载引擎等文件,xldl.dll为API接口,通过调用此文件来进行下载,xldl.h为一些定义的头文件。

     

    首先将压缩包内的文件解压到项目的Debug或Release目录。

    将xldl.h添加到项目中, 并在主程序中引用。

     

    #include "stdafx.h"
    #include <Windows.h>
    #include <Shlwapi.h>
    #pragma comment(lib,"shlwapi.lib") 
    #include <string>
    #include <iostream>
    #include <iomanip>
    #include "xldl.h"
    

    既然只提供了DLL和H,那就得LoadLibrary动态调用了(吐槽一下没静态调用,还得自己导入函数)。

      新建并引入DownWrapper.h,供引入XLDL.DLL

    // xldl.dll导出函数的封装类
    
    #pragma once
    
    // 定义函数指针
    typedef BOOL(*fn_Init)(void);
    typedef BOOL(*fn_UnInit)(void);
    typedef HANDLE(*fn_TaskCreate)(DownTaskParam &stParam);
    typedef BOOL(*fn_TaskDelete)(HANDLE hTask);
    typedef BOOL(*fn_TaskStart) (HANDLE hTask);
    typedef BOOL(*fn_TaskPause) (HANDLE hTask);
    typedef BOOL(*fn_TaskQuery) (HANDLE hTask, DownTaskInfo &stTaskInfo);
    typedef BOOL(*fn_TaskQueryEx) (HANDLE hTask, DownTaskInfo &stTaskInfo);
    typedef void(*fn_LimitSpeed)(INT32 nKBps);
    typedef void(*fn_LimitUploadSpeed)(INT32 nTcpBps, INT32 nOtherBps);
    typedef BOOL(*fn_DelTempFile)(DownTaskParam &stParam);
    typedef BOOL(*fn_SetProxy)(DOWN_PROXY_INFO &stProxy);
    typedef void(*fn_SetUserAgent)(const TCHAR* pszUserAgent);
    typedef BOOL(*fn_GetFileSizeWithUrl)(const wchar_t * lpURL, INT64& iFileSize);
    typedef BOOL(*fn_ParseThunderPrivateUrl)(const TCHAR *pszThunderUrl, TCHAR *normalUrlBuffer, INT32 bufferLen);
    typedef LONG(*fn_SetAdditionInfo)(HANDLE task_id, WSAPROTOCOL_INFOW *sock_info, CHAR *http_resp_buf, LONG buf_len);
    typedef BOOL(*fn_SetFileIdAndSize)(HANDLE hTask, char szFileId[40], unsigned __int64 nFileSize);
    typedef HANDLE(*fn_CreateTaskByURL)(const wchar_t *url, const wchar_t *path, const wchar_t *fileName, BOOL IsResume);
    
    #define CHECKFUNC(f, ret) if (f == NULL) return ret;
    #define CHECKFUNC_(f) if (f == NULL) return;
    
    class DownWrapper
    {
    public:
    
      DownWrapper(LPCWSTR sPath)
      {
        m_hModule = ::LoadLibraryW(sPath);
        if (m_hModule == NULL)
        {
          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_TaskPause)       ::GetProcAddress(m_hModule, "XL_StopTask");
        _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");
      }
    
      virtual ~DownWrapper(void)
      {
        if (m_hModule)
        {
          ::FreeLibrary(m_hModule);
        }
      }
    
      BOOL Init()
      {
        CHECKFUNC(_Init, FALSE); return _Init();
      }
      BOOL UnInit()
      {
        CHECKFUNC(_UnInit, FALSE); return _UnInit();
      }
      HANDLE TaskCreate(DownTaskParam &param)
      {
        CHECKFUNC(_TaskCreate, NULL); return _TaskCreate(param);
      }
      BOOL TaskDelete(HANDLE hTask)
      {
        CHECKFUNC(_TaskDelete, FALSE); return _TaskDelete(hTask);
      }
      BOOL TaskStart(HANDLE hTask)
      {
        CHECKFUNC(_TaskStart, FALSE); return _TaskStart(hTask);
      }
      BOOL TaskPause(HANDLE hTask)
      {
        CHECKFUNC(_TaskPause, FALSE); return _TaskPause(hTask);
      }
      BOOL TaskQuery(HANDLE hTask, DownTaskInfo & stTaskInfo)
      {
        CHECKFUNC(_TaskQuery, FALSE); return _TaskQuery(hTask, stTaskInfo);
      }
      BOOL TaskQueryEx(HANDLE hTask, DownTaskInfo & stTaskInfo)
      {
        CHECKFUNC(_TaskQueryEx, FALSE); return _TaskQueryEx(hTask, stTaskInfo);
      }
      void LimitSpeed(INT32 nBps)
      {
        CHECKFUNC_(_LimitSpeed);  _LimitSpeed(nBps);
      }
      void LimitUploadSpeed(INT32 nTcpBps, INT32 nOtherBps)
      {
        CHECKFUNC_(_LimitUploadSpeed);  _LimitUploadSpeed(nTcpBps, nOtherBps);
      }
      BOOL DelTempFile(DownTaskParam &stParam)
      {
        CHECKFUNC(_DelTempFile, FALSE); return _DelTempFile(stParam);
      }
      BOOL SetProxy(DOWN_PROXY_INFO &stProxy)
      {
        CHECKFUNC(_SetProxy, FALSE); return _SetProxy(stProxy);
      }
      void SetUserAgent(const TCHAR *pszUserAgent)
      {
        CHECKFUNC_(_SetUserAgent); _SetUserAgent(pszUserAgent);
      }
      BOOL GetFileSizeWithUrl(const wchar_t * lpURL, INT64& iFileSize)
      {
        CHECKFUNC(_GetFileSizeWithUrl, FALSE); return _GetFileSizeWithUrl(lpURL, iFileSize);
      }
      BOOL ParseThunderPrivateUrl(const TCHAR *pszThunderUrl, TCHAR *normalUrlBuffer, INT32 bufferLen)
      {
        if (_ParseThunderPrivateUrl == NULL) return FALSE; return _ParseThunderPrivateUrl(pszThunderUrl, normalUrlBuffer, bufferLen);
      }
      LONG SetAdditionInfo(HANDLE task_id, WSAPROTOCOL_INFOW *sock_info, CHAR *http_resp_buf, LONG buf_len)
      {
        CHECKFUNC(_SetAdditionInfo, FALSE); return _SetAdditionInfo(task_id, sock_info, http_resp_buf, buf_len);
      }
      LONG SetFileIdAndSize(HANDLE hTask, char szFileId[40], unsigned __int64 nFileSize)
      {
        CHECKFUNC(_SetFileIdAndSize, FALSE); return _SetFileIdAndSize(hTask, szFileId, nFileSize);
      }
      HANDLE TaskCreateByUrl(const wchar_t *url, const wchar_t *path, const wchar_t *fileName, BOOL IsResume)
      {
        CHECKFUNC(_CreateTaskByURL, NULL); return _CreateTaskByURL(url, path, fileName, IsResume);
      }
    private:
      HMODULE           m_hModule;
    
      fn_Init           _Init;
      fn_UnInit         _UnInit;
      fn_TaskCreate       _TaskCreate;
      fn_TaskDelete       _TaskDelete;
      fn_TaskStart        _TaskStart;
      fn_TaskPause        _TaskPause;
      fn_TaskQuery        _TaskQuery;
      fn_TaskQueryEx        _TaskQueryEx;
      fn_LimitSpeed       _LimitSpeed;
      fn_LimitUploadSpeed     _LimitUploadSpeed;
      fn_DelTempFile        _DelTempFile;
      fn_SetProxy         _SetProxy;
      fn_SetUserAgent       _SetUserAgent;
      fn_GetFileSizeWithUrl   _GetFileSizeWithUrl;
      fn_ParseThunderPrivateUrl _ParseThunderPrivateUrl;
      fn_SetAdditionInfo      _SetAdditionInfo;
      fn_SetFileIdAndSize     _SetFileIdAndSize;
      fn_CreateTaskByURL      _CreateTaskByURL;
    };
    

    然后定义一个DownWrapper LoadDLL

    // 加载xldl.dll
    DownWrapper* LoadDll()
    {
      WCHAR szModulePath[MAX_PATH] = {0};
      ::GetModuleFileName(NULL, szModulePath, MAX_PATH);
      ::PathRemoveFileSpec(szModulePath);
    
      WCHAR szDllpath[MAX_PATH] = {0};
      ::PathCombine(szDllpath, szModulePath, L"xldl.dll");
      OutputDebugString(szDllpath);
    
      DownWrapper* pWapper = new DownWrapper(szDllpath);
      return pWapper;
    }
    

    在主函数中调用并执行下载:

    int main(){
      // 加载xldl.dll, 返回导出函数的封装类
      DownWrapper* pWapper = LoadDll();
      // 初始化下载引擎
      if (!pWapper->Init())
      {
        cout << "引擎初始化失败" << endl;
        return 1;
      }
      //默认的下载函数参数内容太多,而且在一般下载中用不到,所以我特意定义并调用了封装函数CreateTaskByUrl
      HANDLE dlhd = pWapper->TaskCreateByUrl(L"http://blog.eqoe.cn/archives/thunder-sdk.html", L".\\", L"thunder-sdk.html", FALSE); //创建任务并获得下载句柄 第四个参数指示任务是新建还是续传
      if (pWapper->TaskStart(dlhd) == FALSE){//开始下载任务
        return 2;
      }
      DownTaskInfo DLINFO;//定义一个任务信息变量
      while (true){//循环
        pWapper->TaskQueryEx(dlhd, DLINFO);//查询任务信息
        cout << "下载速度: " << DLINFO.nSpeed / 1024 << "KB/s" << endl;
        cout << "文件大小: " << DLINFO.nTotalSize / 1024 / 1024 << "MB" <<endl;
        cout << "已经下载: " << DLINFO.nTotalDownload / 1024 / 1024 << "MB" <<endl;
        Sleep(1000);
        if (DLINFO.stat == TSC_COMPLETE){//如果已经下载完成
          pWapper->UnInit();//反初始化(从内存中卸载)迅雷下载模块
          break;//跳出循环
        }
      }
      return 0;
    }
    

    调用过程就是这样,官方虽然说非线程安全,但是查询任务信息等操作还是可以在其他线程上执行的,如果是窗口程序,可以将上面输出任务信息改为更改界面文字内容等,然后新建线程循环查询任务信息并Redraw窗口组件,从而不阻塞UI线程。

    SDK还有很多其他接口,用途等,这里就不一一赘述了。