C++调用迅雷接口解析XML下载功能(迅雷下载功能)

所属分类: 软件编程 / C 语言 阅读数: 118
收藏 0 赞 0 分享

迅雷下载库的网址:http://thunderplatform.xunlei.com

复制代码 代码如下:

// FileName: Download.h
#pragma once
#include "lib\XLDownload.h"
#include "lib\XLError.h"
#include <vector>

// 下载队列的大小,决定同时开启下载线程的数量
const int LIMIT = 2;

struct Down
{
    // 解析出来的下载地址
    CString strDownURL;
    // 保存的路径
    CString strSavePath;
};

struct Flag
{
    DWORD dwFlag;            // 记录下载线程实时状态
    LONG lTaskId;            // 记录对应任务ID号
    ULONGLONG ullFileSize;    // 下载文件大小
    ULONGLONG ullRecvSize;    // 已下载大小
};

class CDownload
{
private:

    // 保存下载的日志信息
    std::vector<CString> strLogArr;

    // 解析XML文件
    //void Analysis (LPCTSTR lpPathXML, LPCTSTR lpBegin, LPCTSTR lpEnd);
    void Analysis (LPCTSTR lpPathXML);

    // 开始下载
    void Start (void);

    // 调用迅雷的下载接口
    void CreateDownThread (int n);

    // 下载任务查询监控线程
    static void DownQury (LPVOID ptr);

    // 保存日志
    void SaveLog (LPCTSTR lpPathAndName);

public:

    // 保存解析出来的下载队列
    std::vector<Down> strDownArr;

    // 记录最新的下载位置
    int m_nIndex;

    // 下载队列的大小,对应位为1时,该下载位为空,可以启动新的下载线程
    struct Flag Flags[LIMIT];

    // 总共的下载数
    int m_nTotal;

    // 失败的下载数
    int m_nFail;

    // 成功的下载数
    int m_nSuccess;

    CDownload();
    ~CDownload();
    BOOL DownloadFilesByXML(LPCTSTR lpPahtXML);
};

复制代码 代码如下:

// FileName: Download.cpp
#include "stdafx.h"
#include "Download.h"
#include <Shlwapi.h>
#include <locale.h>
#pragma comment(lib, "lib\\XLDownload.lib")

// 包含XTP界面库头文件
#include "XTToolkitPro.h"

CDownload::CDownload()
{
    // 初始化
    m_nIndex = 0;

    // 初始化为没有下载线程
    for (int n=0; n<LIMIT; n++)
    {
        Flags[n].dwFlag = 1;
        Flags[n].lTaskId = n;
    }

    m_nSuccess = 0;
    m_nTotal = 0;
    m_nFail = 0;
}

CDownload::~CDownload()
{

}

BOOL CDownload::DownloadFilesByXML(LPCTSTR lpPathXML)
{
    DWORD dwRet = XL_SUCCESS;

    // 检测XML文件是否存在
    if (!PathFileExists(lpPathXML))
    {
        ::MessageBox(NULL, _T("XML文件不存在!"), _T("友情提示"), MB_OK|MB_ICONEXCLAMATION);   
        return FALSE;
    }

    // 解析XML文件
    Analysis(lpPathXML);

    // 统计下载链接数
    m_nTotal = strDownArr.size();

    // 开始下载
    Start();

    return TRUE;
}

//void CDownload::Analysis(LPCTSTR lpPathXML, LPCTSTR lpBegin, LPCTSTR lpEnd)
void CDownload::Analysis(LPCTSTR lpPathXML)
{
    // 读取XML文件
    CXTPPropExchangeXMLNode px(TRUE, NULL, _T("DownLoadInfo"));

    if (!px.LoadFromFile(lpPathXML))
    {

        ::MessageBox(NULL, _T("打开XML文件出错!"), _T("友情提示"), MB_OK|MB_ICONEXCLAMATION);
        return;
    }

    if (!px.OnBeforeExchange())
    {
        ::MessageBox(NULL, _T("OnBeforeExchange false!"), _T("友情提示"), MB_OK|MB_ICONEXCLAMATION);
        return;
    }

    px.SetCompactMode(TRUE);

    CXTPPropExchangeEnumeratorPtr enumItem(px.GetEnumerator(_T("Item")));
    POSITION posItem = enumItem->GetPosition();

    CString strLocalName;
    Down down;

    // 遍历所有的结点
    while (posItem)
    {
        CXTPPropExchangeSection sec(enumItem->GetNext(posItem));

        if (sec->IsLoading())
        {
            PX_String(sec->GetSection(_T("URL")), NULL, down.strDownURL);
            PX_String(sec->GetSection(_T("LocalPath")), NULL, down.strSavePath);
            PX_String(sec->GetSection(_T("LocalName")), NULL, strLocalName);

            down.strSavePath += strLocalName;
            // 路径转换
            down.strSavePath.Replace('/', '\\');

            strDownArr.push_back(down);
        }
    }
}

// 下载任务查询
void CDownload::DownQury (LPVOID ptr)
{
    CDownload* pDown = (CDownload*)ptr;
    bool nSign = true;
    DWORD dwRst;
    TCHAR errorBuf[500];
    DWORD dwSize = 500;
    CString strLog;

    // 如果没有下载完成一直下载
    while ((pDown->m_nIndex < (pDown->strDownArr).size()) || nSign)
    {
        int n = 0;
        LONG temp = -1;
        nSign = false;

        while (n<LIMIT)
        {
            switch(pDown->Flags[n].dwFlag)
            {
                // 没有下载,开始新的下载
                case 1 :
                    pDown->CreateDownThread(n);
                    dwRst = XLQueryTaskInfo(pDown->Flags[n].lTaskId, &temp, &(pDown->Flags[n].ullFileSize), &(pDown->Flags[n].ullRecvSize));

                    if (dwRst == XL_SUCCESS && pDown->m_nIndex<pDown->strDownArr.size())
                    {
                        pDown->strLogArr.push_back(pDown->strDownArr[pDown->m_nIndex].strDownURL);
                        pDown->strLogArr.push_back(_T("state:suceess"));
                        pDown->Flags[n].dwFlag = temp;
                    }
                    else
                    {
                        if (pDown->m_nIndex < pDown->strDownArr.size())
                        {
                            pDown->m_nFail += 1;
                            XLGetErrorMsg(dwRst, errorBuf, dwSize);
                            pDown->strLogArr.push_back(pDown->strDownArr[pDown->m_nIndex].strDownURL);
                            strLog.Format(_T("state:%s"), errorBuf);
                            pDown->strLogArr.push_back(strLog);
                        }
                        pDown->m_nIndex += 1;
                    }
                    break;

                // 成功下载完, 开始新的下载
                case 11:
                    pDown->CreateDownThread(n);
                    dwRst = XLQueryTaskInfo(pDown->Flags[n].lTaskId, &temp, &(pDown->Flags[n].ullFileSize), &(pDown->Flags[n].ullRecvSize));
                    if (dwRst == XL_SUCCESS && pDown->m_nIndex<pDown->strDownArr.size())
                    {
                        pDown->strLogArr.push_back(pDown->strDownArr[pDown->m_nIndex].strDownURL);
                        pDown->strLogArr.push_back(_T("state:suceess"));
                        pDown->Flags[n].dwFlag = temp;
                    }
                    else
                    {
                        if (pDown->m_nIndex < pDown->strDownArr.size())
                        {
                            pDown->m_nFail += 1;
                            XLGetErrorMsg(dwRst, errorBuf, dwSize);
                            pDown->strLogArr.push_back(pDown->strDownArr[pDown->m_nIndex].strDownURL);
                            strLog.Format(_T("state:%s"), errorBuf);
                            pDown->strLogArr.push_back(strLog);
                        }
                        pDown->m_nIndex += 1;
                    }
                    break;

                // 下载失败,开始新的下载
                case 12:
                    pDown->CreateDownThread(n);
                    dwRst = XLQueryTaskInfo(pDown->Flags[n].lTaskId, &temp, &(pDown->Flags[n].ullFileSize), &(pDown->Flags[n].ullRecvSize));
                    if (dwRst == XL_SUCCESS && pDown->m_nIndex<pDown->strDownArr.size())
                    {
                        pDown->strLogArr.push_back(pDown->strDownArr[pDown->m_nIndex].strDownURL);
                        pDown->strLogArr.push_back(_T("state:suceess"));
                        pDown->Flags[n].dwFlag = temp;
                    }
                    else
                    {
                        if (pDown->m_nIndex < pDown->strDownArr.size())
                        {
                            pDown->m_nFail += 1;
                            XLGetErrorMsg(dwRst, errorBuf, dwSize);
                            pDown->strLogArr.push_back(pDown->strDownArr[pDown->m_nIndex].strDownURL);
                            strLog.Format(_T("state:%s"), errorBuf);
                            pDown->strLogArr.push_back(strLog);
                        }
                        pDown->m_nIndex += 1;
                    }
                    break;

                // 默认处理
                default:
                    XLQueryTaskInfo(pDown->Flags[n].lTaskId, &temp, &(pDown->Flags[n].ullFileSize), &(pDown->Flags[n].ullRecvSize));
                    pDown->Flags[n].dwFlag = temp;
                    if (temp == enumTaskStatus_Download)
                    {
                        nSign = true;
                    }
            }
            n++;
        }
        //Sleep(1);
    }

    // 保存日志
    pDown->SaveLog(_T("C:\\down.log"));

    CString strTemp;
    strTemp.Format(_T("下载完成! 下载总数:%d 成功总数%d 失败总数%d 日志存在位置:C:\\down.log"), pDown->m_nTotal, pDown->m_nSuccess, pDown->m_nFail);
    ::MessageBox(NULL, strTemp, _T("友情提示"), MB_OK);

    pDown->m_nSuccess = 0;
    pDown->m_nTotal = 0;
    pDown->m_nFail = 0;

    // 恢复初始状态
    pDown->m_nIndex = 0;

    // 恢复为下载队列为空
    for (int n=0; n<LIMIT; n++)
    {
        pDown->Flags[n].dwFlag = 1;
        pDown->Flags[n].lTaskId = n;
        // 无论是否下载成功,都必须调用XLStopTask
        XLStopTask(pDown->Flags[n].lTaskId);
    }

    //释放资源
    XLUninitDownloadEngine();
}

void CDownload::Start (void)
{
    int nIndex = 0;

    // 1、初始化下载引擎
    if ( FALSE == XLInitDownloadEngine() )
    {
        ::MessageBox(NULL, _T("初始化下载引擎失败!"), _T("友情提示"), MB_OK|MB_ICONEXCLAMATION);
        return;
    }

    // 下载任务查询监控线程
    ::CreateThread (NULL, 0, (LPTHREAD_START_ROUTINE)DownQury, this, 0, NULL);
}

// 调用迅雷的下载接口
void CDownload::CreateDownThread (int n)
{
    DWORD dwRst = 0;
    if (m_nIndex < strDownArr.size())
    {
        dwRst = XLURLDownloadToFile(strDownArr[m_nIndex].strSavePath, strDownArr[m_nIndex].strDownURL, NULL, Flags[n].lTaskId);
        if (dwRst == XL_SUCCESS)
        {
            Flags[n].dwFlag = enumTaskStatus_Download;
            m_nIndex++;
            m_nSuccess++;
        }
    }
    else
    {
        m_nIndex = strDownArr.size();
    }
}

void CDownload::SaveLog (LPCTSTR lpPathAndName)
{
    CStdioFile file;
    std::vector<CString>::iterator iter;

    // 保存现在的语言环境
    char * old_locale = _strdup(setlocale(LC_CTYPE,NULL));
    // 设置中文环境
    setlocale(LC_CTYPE, "chs");

    if (file.Open(lpPathAndName, CFile::modeCreate|CFile::modeWrite))
    {
        for (iter=strLogArr.begin(); iter!=strLogArr.end(); iter++)
        {
            file.WriteString(*iter);
            file.WriteString(_T("\n"));
        }
    }
    file.Close();
    // 还原语言区域的设置
    setlocale(LC_CTYPE, old_locale);
    //  释放内存
    free(old_locale);
}

更多精彩内容其他人还在看

用标准c++实现string与各种类型之间的转换

这个类在头文件中定义, < sstream>库定义了三种类:istringstream、ostringstream和stringstream,分别用来进行流的输入、输出和输入输出操作。另外,每个类都有一个对应的宽字符集版本
收藏 0 赞 0 分享

C++如何通过ostringstream实现任意类型转string

再使用整型转string的时候感觉有点棘手,因为itoa不是标准C里面的,而且即便是有itoa,其他类型转string不是很方便。后来去网上找了一下,发现有一个好方法
收藏 0 赞 0 分享

C/C++指针小结

要搞清一个指针需要搞清指针的四方面的内容:指针的类型,指针所指向的类型,指针的值或者叫指针所指向的内存区,还有指针本身所占据的内存区
收藏 0 赞 0 分享

C++ 类的静态成员深入解析

在C++中类的静态成员变量和静态成员函数是个容易出错的地方,本文先通过几个例子来总结静态成员变量和成员函数使用规则,再给出一个实例来加深印象
收藏 0 赞 0 分享

C++类的静态成员初始化详细讲解

通常静态数据成员在类声明中声明,在包含类方法的文件中初始化.初始化时使用作用域操作符来指出静态成员所属的类.但如果静态成员是整型或是枚举型const,则可以在类声明中初始化
收藏 0 赞 0 分享

C++类静态成员与类静态成员函数详解

静态成员不可在类体内进行赋值,因为它是被所有该类的对象所共享的。你在一个对象里给它赋值,其他对象里的该成员也会发生变化。为了避免混乱,所以不可在类体内进行赋值
收藏 0 赞 0 分享

C++中的friend友元函数详细解析

友元可以是一个函数,该函数被称为友元函数;友元也可以是一个类,该类被称为友元类。友元函数的特点是能够访问类中的私有成员的非成员函数。友元函数从语法上看,它与普通函数一样,即在定义上和调用上与普通函数一样
收藏 0 赞 0 分享

static全局变量与普通的全局变量的区别详细解析

以下是对static全局变量与普通的全局变量的区别进行了详细的分析介绍,需要的朋友可以过来参考下,希望对大家有所帮助
收藏 0 赞 0 分享

C++ explicit关键字的应用方法详细讲解

C++ explicit关键字用来修饰类的构造函数,表明该构造函数是显式的,既然有"显式"那么必然就有"隐式",那么什么是显示而什么又是隐式的呢?下面就让我们一起来看看这方面的知识吧
收藏 0 赞 0 分享

教你5分钟轻松搞定内存字节对齐

随便google一下,人家就可以跟你解释的,一大堆的道理,我们没怎么多时间,讨论为何要对齐.直入主题,怎么判断内存对齐规则,sizeof的结果怎么来的,请牢记以下3条原则
收藏 0 赞 0 分享
查看更多