场景:
1. 在Windows编程时, 下载http页面(html,xml)能够使用winhttp库,可是并非非常下载文件,由于会失败. 由此引出了WinINet库,无奈这个库的稳定性比較低,使用样例又少,
下载大文件时常常是不完整,可查找的资料非常少或者是没有特殊情况的解决的方法。
2. 我的原则是假设系统有自带的就用系统的,可是 WinINet 要掌握须要花不少时间. 时间因素考虑到了libcurl.
3. libcurl支持ftp,http等协议的文件读取,还能自己主动获取文件大小, 最重要的是不须要怎么改动就能稳定支持完整下载大文件,还能支持跨平台(Windows,MacOSX)。
參考编译后的curl.exe使用:
curl.exe -O http://img.ptcms.csdn.net/article/201506/25/558bbe1baed6e.jpg
之前也有写libcurl的使用的其它场景:
[libcurl]_[C/C++]_[使用libcurl库做简单软件更新解决方式]
编译mingw库非常容易,直接依赖windows本地库即可,要编译msvc版本号的话须要进入 winbuild 文件夹,參考 BUILD.WINDOWS.txt 里的
nmake /f Makefile.vc mode=<static or dll> <options>
我用的配置
nmake /f Makefile.vc mode=dll VC=10 ENABLE_IDN=no
http_download_domain.h
#ifndef __HTTP_DOWNLOAD_DOMAIN #define __HTTP_DOWNLOAD_DOMAIN #include <string> #include "curl/curl.h" class HttpDownloadDomain { public: HttpDownloadDomain(bool* cancel); ~HttpDownloadDomain(); bool DownloadFile(std::string url,std::wstring path); bool *cancel_; private: static size_t DownloadCallback(void* pBuffer, size_t nSize, size_t nMemByte, void* pParam); static int ProgressCallback(void *clientp, double dltotal, double dlnow, double ultotal, double ulnow); }; #endif
http_download_domain.cpp
#include "stdafx.h" #include "http_download_domain.h" #include <iostream> HttpDownloadDomain::HttpDownloadDomain(bool* cancel) { cancel_ = cancel; } HttpDownloadDomain::~HttpDownloadDomain() { } size_t HttpDownloadDomain::DownloadCallback(void* pBuffer, size_t nSize, size_t nMemByte, void* pParam) { FILE* fp = (FILE*)pParam; size_t nWrite = fwrite(pBuffer, nSize, nMemByte, fp); return nWrite; } int HttpDownloadDomain::ProgressCallback(void *clientp, double dltotal, double dlnow, double ultotal, double ulnow) { HttpDownloadDomain* dd = (HttpDownloadDomain*)clientp; if ( dltotal > -0.1 && dltotal < 0.1 ) { return 0; } int nPos = (int) ( (dlnow/dltotal)*100 ); //通知进度条更新下载进度 std::cout << "dltotal: " << (long)dltotal << " ---- dlnow:" << (long)dlnow << std::endl; if(*dd->cancel_) { //1. 返回非0值就会终止 curl_easy_perform 运行 return -2; } return 0; } bool HttpDownloadDomain::DownloadFile(std::string URLADDR,std::wstring path) { //初始化curl,这个是必须的 CURL *curl = curl_easy_init(); curl_easy_setopt(curl, CURLOPT_URL, URLADDR.c_str()); //设置接收数据的回调 FILE* file = _wfopen(path.c_str(), L"wb"); curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, DownloadCallback); curl_easy_setopt(curl, CURLOPT_WRITEDATA,file); curl_easy_setopt(curl, CURLOPT_MAXREDIRS, 5); curl_easy_setopt(curl, CURLOPT_FOLLOWLOCATION, 1); curl_easy_setopt(curl, CURLOPT_NOPROGRESS, 0); curl_easy_setopt(curl, CURLOPT_PROGRESSFUNCTION, ProgressCallback); curl_easy_setopt(curl, CURLOPT_PROGRESSDATA,this); CURLcode retcCode = curl_easy_perform(curl); const char* pError = curl_easy_strerror(retcCode); std::cout << "pError: " << pError << std::endl; fclose(file); //清理curl,和前面的初始化匹配 curl_easy_cleanup(curl); return !retcCode; }
使用方式:
#include "stdafx.h" #include "http_download_domain.h" int _tmain(int argc, _TCHAR* argv[]) { bool i = 0; HttpDownloadDomain hdd(&i); hdd.DownloadFile("http://img.ptcms.csdn.net/article/201506/25/558bbe1baed6e.jpg",L"C:\Users\apple\Downloads\558bbe1baed6e.jpg"); system("pause"); return 0; }
下载完整样例:
http://download.csdn.net/detail/infoworld/8840787