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

迅雷下载库的网址: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);
}

(0)

相关推荐

  • C++通过COM接口操作PPT

    一. 背景说明 在VS环境下,开发C++代码操作PPT,支持对PPT模板的修改.包括修改文本标签.图表.表格.满足大多数软件生成PPT报告的要求,先手工创建好PPT模板,在程序中修改模板数据. 二. 开发环境构建 通过VS2012的Class Wizard创建PowerPoint和Excel的COM接口:由于需要操作PPT中的图表,而图表的数据使用Excel存储的,需要修改图表的数据就得生成Excel的COM接口. 1.1 进入类向导 1.2 添加PowerPoint COM接口 1.3 添加E

  • C++实现“隐藏实现,开放接口”的方案

    为什么要有接口? 接口就是一个程序与其它程序交流的窗口.就比如有一个电视机,我并不需要知道它是怎样工作的,我只要知道按电源键就可以开启电视,按节目加(+)减(-)可以切换电视频道就可以了. Java程序员都知道Java中有interface可以实现对外的接口,但C++并没有接口这样的语法,那它要好怎样实现对外提供接口呢?我们可以通过纯虚函数定义一个抽象类,专门用来声明一个类的功能. 我们完成了一个程序模块的开发,要把这个程序模块给别人用,你肯定不会把源代码给他(那别人就完全撑屋你的技术了),你会

  • SQLite教程(二):C/C++接口简介

    一.概述: 在SQLite提供的C/C++接口中,其中5个APIs属于核心接口.在这篇博客中我们将主要介绍它们的用法,以及它们所涉及到的核心SQLite对象,如database_connection和prepared_statement.相比于其它数据库引擎提供的APIs,如OCI.MySQL API等,SQLite提供的接口还是非常易于理解和掌握的.     二.核心对象和接口: 1. 核心对象:     在SQLite中最主要的两个对象是,database_connection和prepar

  • C++编写非侵入式接口

    终于写到c++的非侵入式接口了,兴奋,开心,失望,解脱,-- .在搞了这么多的面向对象科普之后,本人也已经开始不耐烦,至此,不想做太多阐述. 虽然,很早就清楚怎么在c++下搞非侵入式接口,但是,整个框架代码,重构了十几次之后,才终于满意.支持给基本类型添加接口,好比int,char,const char*,double:支持泛型,好比vector,list:支持继承,基类实现的接口,表示子类也继承了对该接口的实现,而且子类也可以拒绝基类的接口,好比鸭子拒绝基类鸟类"会飞",编译时报错:

  • C++ COM编程之什么是接口?

    什么是接口? 说到COM,就不得不说接口了:在进行COM开发的过程中,可以说,我一直都在和各种各样的接口打交道.那接口是什么?对于COM来说,接口是一个包含一个函数指针数组的内存结构,每一个数组元素包含的是一个由组件所实现的函数的地址:所以,对于COM,接口就是这样的一个内存结构,其它东西都是一些COM并不关心的实现细节. 在C++中,可以使用抽象基类来实现COM接口.由于一个COM组件可以支持任意数目的接口,因此对于组件,可以使用抽象基类的多重继承来实现它. 接口的好处 接口提供了两个不同对象

  • C++中抽象类和接口的区别介绍

    1. 如果一个类B在语法上继承(extend)了类A, 那么在语义上类B是一个类A.2. 如果一个类B在语法上实现了(implement)接口I, 那么类B遵从接口I制定的协议. 使用abstract class的根本原因在于, 人们希望通过这样的方式, 表现不同层次的抽象. 而interface的本质是一套协议. 在程序设计的发展中, 人们又发现接口可以用来表示对行为的抽象, 不过, 这只是interface的一种用法不是其本质. 理论结合实际才是最好的学习方式, 不过在这里, 我只想举一些我

  • C++ COM编程之接口背后的虚函数表

    前言 学习C++的人,肯定都知道多态机制:多态就是用父类型别的指针指向其子类的实例,然后通过父类的指针调用实际子类的成员函数.对于多态机制是如何实现的,你有没有想过呢?而COM中的接口就将这一机制运用到了极致,所以,不知道多态机制的人,是永运无法明白COM的.所以,在总结COM时,是非常有必要专门总结一下C++的多态机制是如何实现的. 多态 什么是多态?上面也说了,多态就是用父类型别的指针指向其子类的实例,然后通过父类的指针调用实际子类的成员函数.现在通过代码,让大家切身的体会一下多态: 复制代

  • 浅谈java的接口和C++虚类的相同和不同之处

    C++虚类相当于java中的抽象类,与接口的不同之处是: 1.一个子类只能继承一个抽象类(虚类),但能实现多个接口 2.一个抽象类可以有构造方法,接口没有构造方法 3.一个抽象类中的方法不一定是抽象方法,即其中的方法可以有实现(有方法体),接口中的方法都是抽象方法,不能有方法体,只有声明 4.一个抽象类可以是public.private.protected.default,接口只有public 5.一个抽象类中的方法可以是public.private.protected.default,接口中的

  • C++访问Redis的mset 二进制数据接口封装方案

    需求 C++中使用hiredis客户端接口访问redis: 需要使用mset一次设置多个二进制数据 以下给出三种封装实现方案: 简单拼接方案 在redis-cli中,mset的语法是这样的: 复制代码 代码如下: /opt/colin$./redis-cli mset a 11 b 22 c 333 OK 按照这样的语法拼接后,直接使用hiredis字符串接口redisCommand传递: void msetNotBinary(redisContext *c, const vector<stri

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

    迅雷下载库的网址: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{    // 解析出来的下载

  • 实例解析Ruby程序中调用REXML来解析XML格式数据的用法

    REXML 是由 Sean Russell 编写的库.它不是 Ruby 的唯一 XML 库,但它是很受欢迎的一个,并且是用纯 Ruby 编写( NQXML 也是用 Ruby 编写的, 但 XMLParser 封装了用 C 编写的 Jade 库). 在他的 REXML 概述中,Russell 评论道: 我有这样的问题:我不喜欢令人困惑的 API.有几种用于 Java 实现的 XML 解析器 API.其中大多数都遵循 DOM 或 SAX,并且在基本原理上与不断出现的众多 Java API 非常相似.

  • Java编程调用微信接口实现图文信息推送功能

    本文实例讲述了Java编程调用微信接口实现图文信息等推送功能.分享给大家供大家参考,具体如下: Java调用微信接口工具类,包含素材上传.获取素材列表.上传图文消息内的图片获取URL.图文信息推送. 微信图文信息推送因注意html代码字符串中将双引号(")替换成单引号('),不然信息页面中包含图片将无法显示且图片后面的内容也不会显示 官方文档:http://mp.weixin.qq.com/wiki/home/ StringBuilder sb=new StringBuilder(); sb.a

  • python 调用API接口 获取和解析 Json数据

    任务背景: 调用API接口数据,抽取我们所需类型的数据,并写入指定mysql数据库. 先从宏观上看这个任务,并对任务进行分解: step1:需要学习python下的通过url读取数据的方式: step2:数据解析,也是核心部分,数据格式从python角度去理解,是字典?列表?还是各种嵌套? step3:连接mysql数据库,将数据写入. 从功能上看,该数据获取程序可以分为3个方法,即step1对应方法request_data(),step2对应方法parse_data(),step3对应data

  • Spring是怎么扩展解析xml接口的

    目录 自定义Spring配置 BeanDefinitionParserDelegate DefaultNamespaceHandlerResolver NamespaceHandlerSupport implements NamespaceHandler BeanDefinitionParser ParserContext 自定义Spring配置 Java自定义Spring配置标签 BeanDefinitionParserDelegate 在DefaultBeanDefinitionDocume

  • java实现简单解析XML文件功能示例

    本文实例讲述了java实现简单解析XML文件功能.分享给大家供大家参考,具体如下: package demo; import java.io.File; import java.io.IOException; import javax.xml.parsers.DocumentBuilder; import javax.xml.parsers.DocumentBuilderFactory; import javax.xml.parsers.ParserConfigurationException;

  • PHP调用API接口实现天气查询功能的示例

    天气预报查询接口API,在这里我使用的是国家气象局天气预报接口 使用较多的还有:新浪天气预报接口.百度天气预报接口.google天气接口.Yahoo天气接口等等. 1.查询方式 根据地名查询各城市天气情况 2.请求URL地址 http://route.showapi.com/9-2 3.接口参数说明: 一.系统级参数(所有接入点都需要的参数): 二.应用级参数(每个接入点有自己的参数): 4.返回参数 以JSON格式返回结果 1)系统级参数(所有接入点都会返回的参数) 2)应用级参数(系统级输出

  • PHP用户管理中常用接口调用实例及解析(含源码)

    掌握用户的第一步就是将已经关注的粉丝信息保存起来,这个时候就用到获取用户列表接口.公众号可通过本接口来获取帐号的关注者列表,关注者列表由一串OpenID(加密后的微信号,每个用户对每个公众号的OpenID是唯一的)组成.一次拉取调用最多拉取10000个关注者的OpenID,可以通过多次拉取的方式来满足需求. 一. 获取微信关注用户列表接口调用实例 接口说明 http请求方式:GET 接口调用地址: https://api.weixin.qq.com/cgi-bin/user/get?access

  • java调用微信接口实现网页分享小功能

    本文实例为大家分享了java调用微信接口实现网页分享小功能的具体代码,供大家参考,具体内容如下 // 获取access_token  *注意* 经过实际开发测试,微信分享不支持跨域请求,因此获取access_token的请求必须从服务器发起,否则无法获取到access_token所以以下都是服务端操作 微信接口说明参考地址 参考文章:Java微信分享接口开发详解 一.微信util类 public class ShareConstants { //微信获取ticket的接口 public stat

  • Java中使用DOM和SAX解析XML文件的方法示例

    dom4j介绍 dom4j的项目地址:http://sourceforge.net/projects/dom4j/?source=directory dom4j是一个简单的开源库,用于处理XML. XPath和XSLT,它基于Java平台,使用Java的集合框架,全面集成了DOM,SAX和JAXP. dom4j的使用 下载了dom4j项目之后,解压缩,将其jar包(我的当前版本叫做dom4j-1.6.1.jar)加入class path下面. (Properties->Java Build Pa

随机推荐