码迷,mamicode.com
首页 > Web开发 > 详细

[libcurl]_[初级]_[使用libcurl下载大文件]

时间:2015-06-26 13:01:57      阅读:282      评论:0      收藏:0      [点我收藏+]

标签:libcurl   下载大文件   方案   例子   停止下载   


场景:

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

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


[libcurl]_[初级]_[使用libcurl下载大文件]

标签:libcurl   下载大文件   方案   例子   停止下载   

原文地址:http://blog.csdn.net/infoworld/article/details/46646933

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!