下载使用Http协议,为了做到断点续传,在点击暂停后,将已下载的大小等数据通过Json存入xml中,当继续传输的时候从xml文件中读取大小继续下载(好几个月前写的,真的想不起来了)

bool CHttpDownLoader::DownLoadData(LPCTSTR downloadedUrl, LPCTSTR strSavePath, LPCTSTR configFile)
{
m_InternetSession = new CInternetSession(HTTPINFO, , INTERNET_OPEN_TYPE_PRECONFIG, NULL, NULL, INTERNET_FLAG_DONT_CACHE);
CString strServer;
CString strObject;
DWORD dw;
INTERNET_PORT nPort;
CString strFilePath;
CFileStatus fileStatus;
DWORD start;
DWORD end;
DWORD runtime;
DWORD LocalFileSize; runtime = ;
start = timeGetTime(); //读取本地文件大小
if (CFile::GetStatus(strSavePath, fileStatus))
{
LocalFileSize = fileStatus.m_size;
}
//解析URL字符串并返回服务的类型及组件
AfxParseURL(downloadedUrl, dw, strServer, strObject, nPort);
//判断是否是HTTP服务器
if (dw != AFX_INET_SERVICE_HTTP && dw != AFX_INET_SERVICE_HTTPS)
{
m_ErrorInfo.m_dwError = ;
m_ErrorInfo.m_strErrorMsg = (CString)downloadedUrl + L"网址不是http类型服务器";
ErrorNotifyObserver(&m_ErrorInfo);
return FALSE;
}
try{
m_HttpConnection = m_InternetSession->GetHttpConnection(strServer,
dw == AFX_INET_SERVICE_HTTP ? INTERNET_FLAG_KEEP_CONNECTION : (INTERNET_FLAG_KEEP_CONNECTION | INTERNET_FLAG_SECURE),
nPort);
//二进制存储HTTP下载文件,阻止从缓存中加载文件
m_HttpFile = m_HttpConnection->OpenRequest(_T("GET"), strObject,
NULL, , NULL, NULL,
INTERNET_FLAG_RELOAD | INTERNET_FLAG_TRANSFER_BINARY |
(dw == AFX_INET_SERVICE_HTTP ? INTERNET_FLAG_KEEP_CONNECTION : (INTERNET_FLAG_KEEP_CONNECTION | INTERNET_FLAG_SECURE)));
//发送HTTP请求到指定的服务器。
m_HttpFile->SendRequest(NULL, , NULL, ); DWORD dwFileSize;
CString strFileSize;
CString strBegin;
strBegin.Format(TEXT("%d"), );
//获取文件大小
m_HttpFile->QueryInfo(HTTP_QUERY_CONTENT_LENGTH, dwFileSize);
m_HttpFile->QueryInfo(HTTP_QUERY_CONTENT_LENGTH, strFileSize);
if (dwFileSize != )
{
//对HTTP请求操作添加一个或多个请求头
m_HttpFile->AddRequestHeaders(_T("Range:") + strBegin + _T("-") + strFileSize + _T("\r\n"));
} CFile downloadedFile;
DWORD len;
if (m_overALL == true)
{
USES_CONVERSION;
remove(T2A(strSavePath));
}
//设置下载模式,不存在的话创建文件,存在的话不会清空这个文件
downloadedFile.Open(strSavePath, CFile::modeCreate | CFile::modeNoTruncate | CFile::modeWrite); // 设定每个数据包大小,通过这个调整下载速度,但是如果包特别大的话速度还是特别慢
CHAR szBuf[] = { };
DWORD dwSize = sizeof(szBuf); DWORD fileLength = downloadedFile.GetLength();
downloadedFile.SeekToEnd();
DWORD AllLength = dwFileSize; m_HttpFile->Seek(fileLength, CFile::begin);
ReadTransmisson(configFile);
m_Transmisson.m_httpFileSize = dwFileSize; //判断文件是否已经下载完成
if (LocalFileSize == dwFileSize)
{
if (m_overALL == false)
{
m_ErrorInfo.m_dwError = ;
m_ErrorInfo.m_strErrorMsg = (CString)downloadedUrl + L"文件已经下载";
ErrorNotifyObserver(&m_ErrorInfo);
downloadedFile.Close();
return false;
} }
if (m_Transmisson.m_downloadedFileSize == )
{
while ((len = m_HttpFile->Read(szBuf, dwSize)) > )
{
fileLength += len;
downloadedFile.Write(szBuf, len);
ZeroMemory(szBuf, sizeof(szBuf)); m_Transmisson.m_downloadSpeed = (fileLength * 100.0) / AllLength;
m_Transmisson.m_downloadAddress = downloadedUrl; float fSpeed = ;
fSpeed = (float)fileLength;
fSpeed /= (float)((float)runtime / (float));
m_Transmisson.m_downloadKB = fSpeed / (float); RecordTransmisson(downloadedUrl, configFile, dwFileSize, fileLength, m_Transmisson.m_downloadSpeed, runtime);
m_Transmisson.m_downloadedFileSize = fileLength;
m_Transmisson.m_runTime = runtime;
DownloadedNotifyObserver(&m_Transmisson); end = timeGetTime();
runtime = end - start;
if (runtime == )
{
runtime = ;
}
if (m_exit == false)
{
downloadedFile.Close();
clear();
break;
}
}
}
//文件已经存在,进行断点续传
else
{
if (m_Transmisson.m_downloadAddress!= downloadedUrl)
{
m_ErrorInfo.m_dwError = ;
m_ErrorInfo.m_strErrorMsg = (CString)strSavePath + L"文件下载地址错误";
ErrorNotifyObserver(&m_ErrorInfo);
downloadedFile.Close();
return false;
}
runtime= m_Transmisson.m_runTime+;
DWORD downloadedSize =m_Transmisson.m_downloadedFileSize;
while ((len = m_HttpFile->Read(szBuf, dwSize)) > )
{
double speed = m_Transmisson.m_downloadSpeed;
downloadedSize += len;
fileLength += len;
downloadedFile.Write(szBuf, len);
ZeroMemory(szBuf, sizeof(szBuf));
m_Transmisson.m_downloadSpeed = (fileLength * 100.0) / AllLength;
m_Transmisson.m_downloadedFileSize=fileLength; float fSpeed = ;
fSpeed = (float)fileLength;
fSpeed /= (float)((float)runtime / (float));
m_Transmisson.m_downloadKB = fSpeed / (float);             //存储下载文件大小
            RecordTransmisson(downloadedUrl, configFile, dwFileSize, (int)fileLength, m_Transmisson.m_downloadSpeed, runtime);
DownloadedNotifyObserver(&m_Transmisson); end = timeGetTime() + m_Transmisson.m_runTime;
runtime = end - start;
if (runtime == )
{
runtime = ;
} if (m_exit == false)
{
downloadedFile.Close();
clear();
break;
}
}
}
downloadedFile.Close();
}
catch (CInternetException *e)
{
m_ErrorInfo.m_dwError = e->m_dwError;
TCHAR szErrorMsg[] = { };
e->GetErrorMessage(szErrorMsg, );
m_ErrorInfo.m_strErrorMsg = szErrorMsg ;
ErrorNotifyObserver(&m_ErrorInfo);
e->Delete();
return FALSE;
}
return TRUE;
}

文件存储

void CHttpDownLoader::RecordTransmisson(LPCTSTR downloadedUrl, LPCTSTR configFile, DWORD downloadFileSize, DWORD readedLenght, double downloadedSpeed, DWORD runTime)
{
USES_CONVERSION;
string downloadAddress W2A(downloadedUrl); ofstream in;
in.open(configFile, ios::trunc);
if (!in.is_open())
{
m_ErrorInfo.m_dwError = ;
m_ErrorInfo.m_strErrorMsg = (CString)downloadedUrl + L"文件无法打开";
ErrorNotifyObserver(&m_ErrorInfo);
//没有成功的执行一个程序
}
in.clear();
Document document;
Document::AllocatorType& allocator = document.GetAllocator();
Value root(kObjectType); root.AddMember("DownloadedAddress", StringRef(downloadAddress.c_str()), allocator);
root.AddMember("FileSize", (uint64_t)downloadFileSize, allocator);
root.AddMember("DownLoadSize", (uint64_t)readedLenght, allocator);
root.AddMember("DownLoadPercentage", downloadedSpeed, allocator);
root.AddMember("RunTime", (uint64_t)runTime, allocator); StringBuffer buffer;
Writer<StringBuffer> writer(buffer);
root.Accept(writer);
std::string result = buffer.GetString();
in << result;
in.close();
} void CHttpDownLoader::ReadTransmisson(LPCTSTR configFile)
{
USES_CONVERSION;
FILE *config = fopen(T2A(configFile), "a");
//移动指针到文件末尾
fseek(config, , SEEK_END);
//判断文件是否为空
if (ftell(config) == )
{
fclose(config);
m_Transmisson.m_httpFileSize = ;
m_Transmisson.m_downloadedFileSize = ;
m_Transmisson.m_downloadSpeed = ;
m_Transmisson.m_runTime = ;
configFile = NULL;
return ;
}
else
{
fclose(config);
Document doc;
ifstream ifs(T2A(configFile), ios_base::binary);
string str;
std::copy(std::istream_iterator<unsigned char>(ifs), std::istream_iterator<unsigned char>(), back_inserter(str));
doc.Parse<>(str.c_str());
Value & dress = doc["DownloadedAddress"];
Value & fileSize = doc["FileSize"];
Value & DownLoadedSize = doc["DownLoadSize"];
Value & downloadSpeed = doc["DownLoadPercentage"];
Value & runTime = doc["RunTime"]; m_Transmisson.m_downloadAddress = dress.GetString();
m_Transmisson.m_httpFileSize = fileSize.GetInt();
m_Transmisson.m_downloadedFileSize = DownLoadedSize.GetInt();
m_Transmisson.m_downloadSpeed = downloadSpeed.GetDouble();
m_Transmisson.m_runTime = runTime.GetFloat();
}
configFile = NULL;
return ;
}

观察者模式

HttpDownLoaded.h

class IDownloadObserver
{
public:
//更新下载信息
virtual void UpdateDownloadInfo(CString m_downloadAddress, double speed, DWORD m_httpfileSize, DWORD m_downloadedFileSize, int m_downloadKB, DWORD runTime) = ;
//更新错误信息
virtual void UpdateErrorMsg(DWORD errorID, CString strErrorMsg) = ;
}; class CHttpDownLoader
{
public:
CHttpDownLoader();
virtual ~CHttpDownLoader();
public:
struct Transmisson
{
//下载地址
CString m_downloadAddress;
//文件大小
DWORD m_httpFileSize;
//已下载大小
DWORD m_downloadedFileSize;
//下载百分比
double m_downloadSpeed; int m_downloadKB; DWORD m_runTime; } m_Transmisson; struct ErrorInfo
{
DWORD m_dwError;
CString m_strErrorMsg;
}m_ErrorInfo;
//建立观察者
void SetObserver(IDownloadObserver * pObserver);
//更新下载速度数据
void DownloadedNotifyObserver(Transmisson *pTransmisson);
//更新错误信息数据
void ErrorNotifyObserver(ErrorInfo *m_ErrorInfo);
}
HttpDownLoadDlg.h

class CHttpDownLoadDlg : public CDialogEx, public IDownloadObserver
{
// 构造
public:
CHttpDownLoadDlg(CWnd* pParent = NULL); // 标准构造函数 // 对话框数据
enum { IDD = IDD_HTTPDOWNLOAD_DIALOG }; protected:
virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV 支持 // 实现
protected:
void UpdateDownloadInfo(CString m_downloadAddress, double speed, DWORD m_httpfileSize, DWORD m_downloadedFileSize, int downloadKB, DWORD runTime);
void UpdateErrorMsg(DWORD errorID, CString strErrorMsg);
};
#include "HttpDownLoaded.h"

void CHttpDownLoader::SetObserver(IDownloadObserver * pObserver)
{
m_downloadTransmissonVectors.push_back(pObserver);
m_errorMsgVectors.push_back(pObserver);
} void CHttpDownLoader::DownloadedNotifyObserver(Transmisson *pTransmisson)
{
MSG msg;
for (auto it = m_downloadTransmissonVectors.begin(); it != m_downloadTransmissonVectors.end(); it++)
{
(*it)->UpdateDownloadInfo(pTransmisson->m_downloadAddress, pTransmisson->m_downloadSpeed, pTransmisson->m_httpFileSize, pTransmisson->m_downloadedFileSize, pTransmisson->m_downloadKB, pTransmisson->m_runTime); if (PeekMessage(&msg, NULL, , , PM_REMOVE))
{
if (msg.message == WM_QUIT)
{
ExitProcess();
}
TranslateMessage(&msg);
DispatchMessage(&msg);
}
}
} void CHttpDownLoader::ErrorNotifyObserver(ErrorInfo *m_ErrorInfo)
{
for (auto it = m_errorMsgVectors.begin(); it != m_errorMsgVectors.end(); it++)
{
(*it)->UpdateErrorMsg(m_ErrorInfo->m_dwError, m_ErrorInfo->m_strErrorMsg);
}
}
#include "HttpDownLoadDlg.h"

void CHttpDownLoadDlg::UpdateDownloadInfo(CString m_downloadAddress, double  speed, DWORD m_httpfileSize, DWORD m_downloadedFileSize, int downloadKB, DWORD runTime)
{
m_progress.SetPos((int)speed);
CString strPercent, KBsec;
strPercent.Format(L"%d%%", (int)speed);
KBsec.Format(L"%d KB/秒", downloadKB);
SetDlgItemText(IDC_PERCENT_TEXT, strPercent);
SetDlgItemText(IDC_SPEED, KBsec);
if (m_downloadedFileSize == m_httpfileSize)
{
CFile tempFile;
tempFile.Remove(L"E:\\recod.config");
MessageBox(L"文件下载完成!", L"OK", MB_ICONINFORMATION);
exit(EXIT_SUCCESS);
} } void CHttpDownLoadDlg::UpdateErrorMsg(DWORD errorID, CString strErrorMsg)
{ }

代码下载

Http协议的断点续传下载器,使用观察者模式监视下载进度,使用xml保存下载进度。的更多相关文章

  1. IDM下载器使用方法详解:百度网盘下载,视频会员一网打尽!

    一. IDM的设置 [01]IDM插件与各大浏览器的集成 默认情况下,在成功安装IDM后,直接点击这里的选项,会弹出[常规设置],一般情况下直接保持默认的配置即可,如果你使用的是比较小众的浏览器,你可 ...

  2. 我的Android进阶之旅------>Android基于HTTP协议的多线程断点下载器的实现

    一.首先写这篇文章之前,要了解实现该Android多线程断点下载器的几个知识点 1.多线程下载的原理,如下图所示 注意:由于Android移动设备和PC机的处理器还是不能相比,所以开辟的子线程建议不要 ...

  3. 在firefox的flashgot中配置各种下载器

    一.在firefox中安装flashgot下载管理器 flashgot是firefox的一个扩展,在联网的情况下,可以在firefox中的附加组件中搜索flashgot,然后安装. 二.在flashg ...

  4. 基于iOS 10、realm封装的下载器

    代码地址如下:http://www.demodashi.com/demo/11653.html 概要 在决定自己封装一个下载器前,我本以为没有那么复杂,可在实际开发过程中困难重重,再加上iOS10和X ...

  5. 第5章 网页下载器和urllib2模块

    网页下载器:将互联网上URL对应的网页下载到本地的工具 通过网页下载器将互联网中的url网页,存储到本地或内存字符串 python有哪几种网页下载器? 1.urllib2  python官方基础模块 ...

  6. 单片机入门学习笔记5:STC下载器

    STC下载器主要集成了, 1.芯片识别,下载/编程 2.端口识别 3.串口助手 4.KEIL仿真设置 5.芯片选型 6.范例程序 (集成了定时器,串口等例程) 7.波特率计算器 8.定时器计算器 9. ...

  7. 网页站点下载器teleport ultra

    软件名称:teleport ultra 介绍:teleport ultra是一款专门的网页站点下载器,使用这款工具可以方便地下载网页数据,包括网站的文字.图片.flash动画等,可以轻松下载所有的网站 ...

  8. Scrapy入门到放弃04:下载器中间件,让爬虫更完美

    前言 MiddleWare,顾名思义,中间件.主要处理请求(例如添加代理IP.添加请求头等)和处理响应 本篇文章主要讲述下载器中间件的概念,以及如何使用中间件和自定义中间件. MiddleWare分类 ...

  9. Android开发多线程断点续传下载器

    使用多线程断点续传下载器在下载的时候多个线程并发可以占用服务器端更多资源,从而加快下载速度,在下载过程中记录每个线程已拷贝数据的数量,如果下载中断,比如无信号断线.电量不足等情况下,这就需要使用到断点 ...

随机推荐

  1. !HDU 2602 Bone Collector--DP--(裸01背包)

    题意:这题就是一个纯粹的裸01背包 分析:WA了好几次.01背包实现的一些细节没搞懂 1.为什么dp[i][j]赋初值为0而不是value[i].由于第i个石头可能不放! 2.在进行状态转移之前要dp ...

  2. 灵活的运用Model类

    1.定义接口 using System; using System.Collections.Generic; using System.Linq; using System.Web; namespac ...

  3. Redis封装之String

    RedisBase类 /// <summary> /// RedisBase类,是redis操作的基类,继承自IDisposable接口,主要用于释放内存 /// </summary ...

  4. 简单的字符串压缩--C代码

    #include <stdio.h> #include <string.h> bool compress(char *str) { char *p=str,c; ; if(!s ...

  5. 【基础篇】DatePickerDialog日期控件的基本使用(二) ——分别获取年、月、日、时、分

    项目步骤: 1.在Main.xml布局文件中定义对应的组件,Main.xml内容如下: <?xml version="1.0" encoding="utf-8&qu ...

  6. codeforces 140E.New Year Garland

    传送门: 解题思路: 要求相邻两行小球颜色集合不同,并且限制行内小球相邻不同. 由此可得:每行小球排列都是独立与外界的, 所以答案应该是对于所有行的颜色集合分类,在将行内的答案乘到上面. 先考虑如何分 ...

  7. route---设置Linux内核中的网络路由表

    route命令用来显示并设置Linux内核中的网络路由表,route命令设置的路由主要是静态路由.要实现两个不同的子网之间的通信,需要一台连接两个网络的路由器,或者同时位于两个网络的网关来实现. 在L ...

  8. 【Uva 1627】Team them up!

    [Link]: [Description] 给你n个人; 有一些人之间有认识关系 a认识b,b不一定认识a 让你把这n个人分成两组 使得这两组中的每一组: 组内的人与人之间都相互认识. 并且,使得两组 ...

  9. TRIZ系列-创新原理-31-多孔材料原理

    多孔材料原理的详细描写叙述例如以下:1)让物体变成多孔的.或者使用辅助的多孔部件(如插入,覆盖):2)假设一个物体已经是多孔了,那么事先往里面填充某种物质:这个原理提出的原因是,一般机械系统通常都是由 ...

  10. ASPNET 页面编码

    转自:http://www.cnblogs.com/libingql/archive/2009/04/11/1433771.html 设置ASPNET页面编码格式 1.Web.Config设置 < ...