Http协议的断点续传下载器,使用观察者模式监视下载进度,使用xml保存下载进度。
下载使用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保存下载进度。的更多相关文章
- IDM下载器使用方法详解:百度网盘下载,视频会员一网打尽!
一. IDM的设置 [01]IDM插件与各大浏览器的集成 默认情况下,在成功安装IDM后,直接点击这里的选项,会弹出[常规设置],一般情况下直接保持默认的配置即可,如果你使用的是比较小众的浏览器,你可 ...
- 我的Android进阶之旅------>Android基于HTTP协议的多线程断点下载器的实现
一.首先写这篇文章之前,要了解实现该Android多线程断点下载器的几个知识点 1.多线程下载的原理,如下图所示 注意:由于Android移动设备和PC机的处理器还是不能相比,所以开辟的子线程建议不要 ...
- 在firefox的flashgot中配置各种下载器
一.在firefox中安装flashgot下载管理器 flashgot是firefox的一个扩展,在联网的情况下,可以在firefox中的附加组件中搜索flashgot,然后安装. 二.在flashg ...
- 基于iOS 10、realm封装的下载器
代码地址如下:http://www.demodashi.com/demo/11653.html 概要 在决定自己封装一个下载器前,我本以为没有那么复杂,可在实际开发过程中困难重重,再加上iOS10和X ...
- 第5章 网页下载器和urllib2模块
网页下载器:将互联网上URL对应的网页下载到本地的工具 通过网页下载器将互联网中的url网页,存储到本地或内存字符串 python有哪几种网页下载器? 1.urllib2 python官方基础模块 ...
- 单片机入门学习笔记5:STC下载器
STC下载器主要集成了, 1.芯片识别,下载/编程 2.端口识别 3.串口助手 4.KEIL仿真设置 5.芯片选型 6.范例程序 (集成了定时器,串口等例程) 7.波特率计算器 8.定时器计算器 9. ...
- 网页站点下载器teleport ultra
软件名称:teleport ultra 介绍:teleport ultra是一款专门的网页站点下载器,使用这款工具可以方便地下载网页数据,包括网站的文字.图片.flash动画等,可以轻松下载所有的网站 ...
- Scrapy入门到放弃04:下载器中间件,让爬虫更完美
前言 MiddleWare,顾名思义,中间件.主要处理请求(例如添加代理IP.添加请求头等)和处理响应 本篇文章主要讲述下载器中间件的概念,以及如何使用中间件和自定义中间件. MiddleWare分类 ...
- Android开发多线程断点续传下载器
使用多线程断点续传下载器在下载的时候多个线程并发可以占用服务器端更多资源,从而加快下载速度,在下载过程中记录每个线程已拷贝数据的数量,如果下载中断,比如无信号断线.电量不足等情况下,这就需要使用到断点 ...
随机推荐
- java内部类的初始化
public class InnerClassTest { /** * @param args */ public static void main(String[] args) { // TODO ...
- 灵活的运用Model类
1.定义接口 using System; using System.Collections.Generic; using System.Linq; using System.Web; namespac ...
- php实现简单算法2
php实现简单算法2 去弄php手册,里面有数据结构,有数据结构就好办了,我的算法基础那么好. 而且的话有数据结构的话再配合我脑中的那些算法了,我就都ok啦. 在手册里面搜索php数据结构就好 路径如 ...
- shrio 身份认证流程-Realm
身份认证流程 流程如下: 1.首先调用Subject.login(token)进行登录,其会自动委托给Security Manager,调用之前必须通过SecurityUtils. setSecuri ...
- POJ - 3847 Moving to Nuremberg 动归
POJ - 3847 Moving to Nuremberg 题意:一张无向有权图,包括边权和点权,求一点,使得到其他点的点权*边权之和最小 思路: #pragma comment(linker, & ...
- Android控件-TabHost(一)
什么是TabHost? TabHost组件的主要功能是可以进行应用程序分类管理,例如:在用户使用windows操作系统的时候,经常见到如图所示的图形界面. TabHost选项卡,说到这个组件, ...
- 【Henu ACM Round#16 A】 Bear and Game
[链接] 我是链接,点我呀:) [题意] 在这里输入题意 [题解] 看看什么时候t[i]-t[i-1]>15. 输出t[i-1]+15就好. 不存在这样的i就输出min(t[n]+15,90) ...
- PatentTips - System and method to deprivilege components of a virtual machine monitor
BACKGROUND INFORMATION An embodiment of the present invention relates generally to virtualization pl ...
- session timer(一)
功能介绍 SIP并没有为所建立的会话定义存活机制. 虽然用户代理能够通过会话特定的机制推断会话是否超时,可是代理server却做不到这点. 如此一来.代理server有时会无法推断会话是否还是活动的. ...
- 如何覆盖GCE的DHCP MTU选项
如何覆盖GCE的DHCP MTU选项 在GCE上托管的Linux IPSec隧道不能打开谷歌,这与MTU有关.谷歌管理员认为"改变这个值是一件困难的事情"https://cl ...