zoukankan      html  css  js  c++  java
  • [libcurl]_[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 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


  • 相关阅读:
    二叉索引树
    将rst转换为markdown格式
    LeetCode电话号码的字母组合题
    根据文件名列表批量复制文件
    VMware+Alpine代替Docker部署Gogs服务
    wsl安装Ubuntu16.04无法ssh提示Permission denied (publickey)
    json二位数组根据指定键名去重
    thinkphp6 关联模型如何查询已经软删除的数据
    DB2数据库配置步骤(图解)
    基于SpringBoot2.3.1进行AOP原理源码阅读
  • 原文地址:https://www.cnblogs.com/slgkaifa/p/6884716.html
Copyright © 2011-2022 走看看