windows C++ 文件下载

windows下载文件有很多方式,本文主要介绍使用WinInet,URLDownloadToFile,curl这几种下载文件的例子

1._WinInetDownLoadFile

int _WinInetDownLoadFile(CString& strFile, CString& strURL)
{
    BYTE *buf = NULL;
    BOOL bRet = FALSE;
    HINTERNET hInet = NULL;
    HINTERNET hInetUrl = NULL;
    HANDLE hFile = INVALID_HANDLE_VALUE;

    if(strURL.IsEmpty())
    {
        MyTrace(L"%s url为空", __FUNCTIONW__);
        return FALSE;
    }

    while(TRUE)
    {
        hInet = InternetOpen( L"Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1)",INTERNET_OPEN_TYPE_DIRECT,NULL,NULL,0);
        if(NULL == hInet)	
        {
            MyTrace(L"%s InternetOpen失败, error=%ld", __FUNCTIONW__, GetLastError());
            break;
        }

        ULONG ulTimeOut = 30 * 1000;
        bRet = InternetSetOption( hInet, INTERNET_OPTION_CONNECT_TIMEOUT, &ulTimeOut, sizeof( ulTimeOut ) );
        MyTrace(L"%s 设置INTERNET_OPTION_CONNECT_TIMEOUT bret=%d error=%ld", __FUNCTIONW__, bRet, GetLastError());

        bRet = InternetSetOption( hInet, INTERNET_OPTION_RECEIVE_TIMEOUT, &ulTimeOut, sizeof( ulTimeOut ) );
        MyTrace(L"%s 设置INTERNET_OPTION_RECEIVE_TIMEOUT bret=%d error=%ld", __FUNCTIONW__, bRet, GetLastError());

        bRet = InternetSetOption( hInet, INTERNET_OPTION_SEND_TIMEOUT, &ulTimeOut, sizeof( ulTimeOut ) );
        MyTrace(L"%s 设置INTERNET_OPTION_SEND_TIMEOUT bret=%d error=%ld", __FUNCTIONW__, bRet, GetLastError());

        hInetUrl = InternetOpenUrl(hInet,strURL, NULL,0,INTERNET_FLAG_RELOAD,0);
        if (NULL == hInetUrl)	
        {
            MyTrace(L"%s InternetOpenUrl失败,error=%ld", __FUNCTIONW__, GetLastError());
            break;
        }
        bRet = TRUE;
        DWORD nBytesRead = 0;
        DWORD nBytesWrite = 0;
        buf = new(nothrow) BYTE[8*1024];
        if (buf == NULL)
        {
            MyTrace(L"%s 申请内存为空 error=%ld", __FUNCTIONW__, GetLastError());
            break;
        }

        BOOL bok = FALSE;
        int nTime = 0;
        while(1)
        {  
            ZeroMemory(buf, 8*1024);
            nTime++;
            if (nTime % 20 == 0)
            {
                Sleep(20);
            }

            bok = ::InternetReadFile(hInetUrl,buf,sizeof(buf),&nBytesRead);
            if(!bok)
            {
                MyTrace(L"%s InternetReadFile失败,error=%ld", __FUNCTIONW__, GetLastError());
                bRet = FALSE;
                break;
            }

            if(0 == nBytesRead)
            {
                MyTrace(L"%s nBytesRead为空 error=%ld", __FUNCTIONW__, GetLastError());
                break;  
            }
            if(hFile == INVALID_HANDLE_VALUE)
            {
                hFile = CreateFile(strFile,GENERIC_WRITE,FILE_SHARE_READ,NULL,CREATE_ALWAYS,FILE_ATTRIBUTE_NORMAL,0);
                if (INVALID_HANDLE_VALUE == hFile) 
                {
                    MyTrace(L"%s 创建文件%s失败,error=%ld", __FUNCTIONW__, strFile, GetLastError());
                    break;
                }
            }

            if(::WriteFile(hFile,buf,nBytesRead,&nBytesWrite,NULL) && nBytesRead == nBytesWrite)  
            {   
                bRet = TRUE;
            }
            else
            {
                MyTrace(L"%s WriteFile%s失败,error=%ld", __FUNCTIONW__, strFile, GetLastError());
                bRet = FALSE;
                break;
            }
        }
        break;
    }

    if(hInetUrl)
    {
        InternetCloseHandle(hInetUrl);
        hInetUrl = NULL;
    }

    if(hInet)
    {
        InternetCloseHandle(hInet);
        hInet = NULL;
    }

    if(INVALID_HANDLE_VALUE != hFile)
    {
        CloseHandle(hFile);
        hFile = NULL;
    }
    
    if (buf != NULL)
    {
        delete buf;
        buf = NULL;
    }

    return bRet;
}

2.URLDownloadToFile

    HRESULT hr = URLDownloadToFile(0, url, pszFileName, 0, NULL);

3.curl

#include <iostream>
#include <fstream>
#include <curl/curl.h>

// 写入数据的回调函数
size_t WriteData(void* ptr, size_t size, size_t nmemb, std::ofstream* stream)
{
    stream->write(static_cast<char*>(ptr), size * nmemb);
    return size * nmemb;
}

// 分段下载函数
bool DownloadSegment(const std::string& url, std::ofstream& output, long start, long end)
{
    CURL* curl;
    CURLcode res;
    curl = curl_easy_init();
    if (curl) {
        // 设置URL
        curl_easy_setopt(curl, CURLOPT_URL, url.c_str());

        // 设置Range头
        std::string range = std::to_string(start) + "-" + std::to_string(end);
        curl_easy_setopt(curl, CURLOPT_RANGE, range.c_str());

        // 设置写入数据的回调函数
        curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, WriteData);
        curl_easy_setopt(curl, CURLOPT_WRITEDATA, &output);

        // 设置SSL选项
        curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, 1L); // 验证服务器的SSL证书
        curl_easy_setopt(curl, CURLOPT_SSL_VERIFYHOST, 2L); // 验证证书上的主机名

        // 执行请求
        res = curl_easy_perform(curl);

        // 清理
        curl_easy_cleanup(curl);

        if (res != CURLE_OK) {
            std::cerr << "curl_easy_perform() failed: " << curl_easy_strerror(res) << std::endl;
            return false;
        }
        return true;
    }
    return false;
}

// 获取文件大小
long GetFileSize(const std::string& url)
{
    CURL* curl;
    CURLcode res;
    double file_size = 0.0;

    curl = curl_easy_init();
    if (curl) {
        curl_easy_setopt(curl, CURLOPT_URL, url.c_str());
        curl_easy_setopt(curl, CURLOPT_NOBODY, 1L); // 不下载内容
        curl_easy_setopt(curl, CURLOPT_HEADER, 1L); // 只获取头部信息

        // 设置SSL选项
        curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, 1L); // 验证服务器的SSL证书
        curl_easy_setopt(curl, CURLOPT_SSL_VERIFYHOST, 2L); // 验证证书上的主机名

        res = curl_easy_perform(curl);

        if (res == CURLE_OK) {
            res = curl_easy_getinfo(curl, CURLINFO_CONTENT_LENGTH_DOWNLOAD, &file_size);
            if ((res == CURLE_OK) && (file_size > 0.0)) {
                curl_easy_cleanup(curl);
                return static_cast<long>(file_size);
            }
        } else {
            std::cerr << "curl_easy_perform() failed: " << curl_easy_strerror(res) << std::endl;
        }

        curl_easy_cleanup(curl);
    }

    return -1;
}

int main() {
    std::string url = ""; // 替换为实际URL
    std::string output_filename = "";
    long segment_size = 1024 * 1024; // 1MB

    // 获取文件大小
    long file_size = GetFileSize(url);
    if (file_size == -1) {
        std::cerr << "Failed to get file size." << std::endl;
        return 1;
    }

    std::cout << "File size: " << file_size << " bytes" << std::endl;

    // 打开输出文件
    std::ofstream output(output_filename, std::ios::binary);
    if (!output.is_open()) {
        std::cerr << "Failed to open output file." << std::endl;
        return 1;
    }

    // 分段下载
    for (long start = 0; start < file_size; start += segment_size) {
        long end = start + segment_size - 1;
        if (end >= file_size) {
            end = file_size - 1;
        }
        std::cout << "Downloading segment: " << start << "-" << end << std::endl;
        if (!DownloadSegment(url, output, start, end)) {
            std::cerr << "Failed to download segment." << std::endl;
            output.close();
            return 1;
        }
    }

    // 关闭输出文件
    output.close();
    std::cout << "Download complete." << std::endl;

    return 0;
}
  • 6
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值