小妞会装机 -- 一个装机软件的开发笔记(六)
来源:互联网 发布:还珠格格小燕子知乎 编辑:程序博客网 时间:2024/05/14 14:26
本文配套程序下载地址为: http://pan.baidu.com/share/link?shareid=358034&uk=3995556177
下载地址获得了,那就下载吧。最简单的,URLDownloadToFile。如何显示进度呢?URLDownloadToFile提供了一个回调,实现这个回调就可以了
STDMETHODIMP CDownloadFileByHttp::OnProgress(ULONG ulProgress, ULONG ulProgressMax, ULONG ulStatusCode, LPCWSTR szStatusText){ m_eaz->downloadBytes = ulProgress; return S_OK;}
解决了!
但问题又来了,一个镜像2.2G,下载速度200K,要下载3个小时!体验也太差了些。我用迅雷试了一下,可以达到1.4M!看来需要多线程下载啊。
怎么多线程呢?解决方法有两个,一个是像迅雷一样对单个文件多线程下载,这需要服务器支持。另外一个就是讲镜像文件分割,然后同时下载多个小文件。第二个方法有个好处,就是如果中途程序退出了,已经下载的完整文件不需要再下载了。所以选择第二种方法。
于是又改代码,开了5个线程,同时下载5个文件。但是奇怪的是,只有两个文件同时下载。超过两个URLDownloadToFile就返回错误。不解。google一下,原来是ie的限制。ie缺省就只能同时下载2个。晕。怎么办呢?修改ie设置?可是ie版本那么多,都要去改很麻烦。而且修改ie设置的时候估计360又得弹框了,改也改不了。怎么办呢?
又google。找到迅雷sdk库,将sdk集成进来后,安装包大了0.5M,可实验了一下,效果不理想。因为下载单个文件的时候,迅雷sdk是单线程下载,根本不会提高下载速度,而且必须要安装迅雷。另外在托盘处会弹出下载速度,可是速度经常不更新,不靠谱。
于是又google,这下找到一个下载库,libcurl。看了一下例子,调用起来很简单。而且multithread例子很适合,就把这个例子改了改,集成到程序里面去,效果很好。推荐以后下载就用这个库,而且稍稍将multithread例子改一下,就可以支持多线程下载一个文件。
size_t CDownloadFileByHttp::write_data(void *ptr, size_t size, size_t nmemb, void *stream){ CDownloadFileByHttp *htt = (CDownloadFileByHttp *)stream; size_t written = fwrite(ptr, size, nmemb, htt->m_pagefile); htt->m_eaz->downloadBytes += written; return written;}BOOL CDownloadFileByHttp::DownloadFile(){ BOOL ret = FALSE; CStringA aurl = CW2A(m_url); CURL *curl; curl = curl_easy_init(); curl_easy_setopt(curl, CURLOPT_URL, aurl.GetBuffer()); aurl.ReleaseBuffer(); curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, &CDownloadFileByHttp::write_data); CStringA afile = CW2A(m_downloadFilePath); m_pagefile = fopen(afile.GetBuffer(), "wb"); afile.ReleaseBuffer(); if (m_pagefile) curl_easy_setopt(curl, CURLOPT_FILE, this); else goto RETURN; int i = 0; while ( i < 5 ) { if (0 == curl_easy_perform(curl)) { m_status = DOWNLOADED; m_eaz->status = DOWNLOADED; m_eaz->downloadBytes = m_eaz->size; TheDownloadManagerHelper.OneFileDownloaded(m_eaz); LOGEx(L"一个文件下载完成: " + m_downloadFilePath); ret = TRUE; goto RETURN; } else { CString msg; msg.Format(L"Error: Http下载文件失败, file = %s, errorcode = %d", m_downloadFilePath.GetBuffer(), GetLastError()); m_downloadFilePath.ReleaseBuffer(); LOGEx(msg); m_eaz->downloadBytes = 0; i++; } } m_eaz->status = NOT_DOWNLOAD; LOGEx(L"Error: Http下载文件失败: " + m_downloadFilePath); TheDownloadManagerHelper.m_errorCode = -7; // Http下载文件失败RETURN: curl_easy_cleanup(curl); if (m_pagefile) fclose(m_pagefile); return ret;}
跑了一下,速度达到了1.4M,和迅雷一样! 好高兴,哈哈
- 小妞会装机 -- 一个装机软件的开发笔记(六)
- 小妞会装机 -- 一个装机软件的开发笔记 (一)
- 小妞会装机 -- 一个装机软件的开发笔记 (二)
- 小妞会装机 -- 一个装机软件的开发笔记( 三)
- 小妞会装机 -- 一个装机软件的开发笔记( 四)
- 小妞会装机 -- 一个装机软件的开发笔记(五)
- 小妞会装机 -- 一个装机软件的开发笔记(七)
- 小妞会装机 -- 一个装机软件的开发笔记(八)
- win7 开发相关 软件装机
- 装机软件
- 装机软件
- 装机
- 装机
- 装机
- 装机
- 装机
- 装机
- 装机
- 关于Android的nodpi,xhdpi,hdpi,mdpi,ldpi
- 如何在 Windows 8 設定開機啟動程式
- dijkstra算法
- 怎样才能学好Linux
- 移植qt常见错误修改方法
- 小妞会装机 -- 一个装机软件的开发笔记(六)
- Linux块设备驱动实例
- 黑马程序员_Java内存区域
- Android网络连接判断与处理
- 引用类型与基本类型的区别
- php初级面试题
- HDFS 拷贝本地文件至HDFS时的异常[INFO fs.FSInputChecker: Found checksum error]处理方法
- 【spoj1693】【最小割】Coconuts
- adb 打印终端中内存使用情况的方法