vc实现http文件下载

本文介绍了在Windows下实现HTTP文件下载的两种方法:1.利用微软的Internet系列API,虽然简单但对Windows环境依赖性强;2.通过TCP模拟HTTP请求,具有更好的通用性。在Win7+VS2010环境下测试成功,并提供了完整测试Demo的免费下载链接。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

1.前言

通过http下载文件比较普遍,这里简单列举两种方法.1.直接使用微软Internet系列api来实现较为简单,对windows环境依赖性较大,经过测试有少量用户无法进行正确下载 2.通过tcp模拟http文件下载,这个通用性较好

2.代码

1.Internet系列函数实现
bool downLoadFile(const TCHAR *Url, const TCHAR *ptFilePath)
{
    bool bret = false;
    HINTERNET hSession = InternetOpen(TEXT("RookIE/1.0"), INTERNET_OPEN_TYPE_PRECONFIG, NULL, NULL, 0);
    if (hSession != NULL)
    {
        HINTERNET handle2 = InternetOpenUrl(hSession, Url, NULL, 0, INTERNET_FLAG_DONT_CACHE, 0);
        if (handle2 != NULL)
        {
            byte Temp[MAXBLOCKSIZE] = {0};
            ULONG Number = 1;

            DWORD  dwBytesWritten ;
            HANDLE hFile;
            if (INVALID_HANDLE_VALUE != 
                (hFile = CreateFile (ptFilePath, GENERIC_WRITE, 0, 
                NULL, CREATE_ALWAYS, 0, NULL)))
            {
                while (Number > 0)
                {
                    BOOL bRet = InternetReadFile(handle2, Temp, MAXBLOCKSIZE - 1, &Number);

                    WriteFile (hFile, Temp, Number * sizeof (byte), 
                        &dwBytesWritten, NULL);
                }
                CloseHandle(hFile);
                bret = true;
            }
            InternetCloseHandle(handle2);
            handle2 = NULL;
        }
        InternetCloseHandle(hSession);
        hSession = NULL;
    }
    return bret;
}
2.通过tcp模拟http文件请求
bool downTcpFile(const std::string &strurl, const std::string &strfilepath)
{
    bool bret = false;
    std::string strip("");
    int nport = 0;
    std::string strsenddata("");
    if (!strurl.empty() && !strfilepath.empty())
    {
        std::string strsuburl(""), strhost(""), strip(""), strport("80");
        int npos = strurl.find("http://");
        if (npos != -1)
            strhost = strurl.substr(npos + strlen("http://"));
        else
        {
            cout<<"ipmap.txt下载地址http非法"<<endl;
            return bret;
        }

        npos = strhost.find("/");
        if (npos != -1)
        {
            strsuburl = strhost.substr(npos);
            strhost = strhost.substr(0, npos);
        }
        else
        {
            cout<<"ipmap.txt下载地址子域名非法"<<endl;
            return bret;
        }

        npos = strhost.find(":");
        if (npos != -1)
        {
            strip = strhost.substr(0, npos);
            strport = strhost.substr(npos + 1);
        }
        else
            strip = strhost;

        char szbuf[1024] = {0};
        sprintf(szbuf, "GET %s HTTP/1.1\r\nHost: %s\r\n\r\n", strsuburl.c_str(), strhost.c_str());
        INT             nret; 
        SOCKADDR_IN     addr;

        SOCKET          Socket; 
        Socket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);

        int nTvlen = 2000;
        setsockopt(Socket,SOL_SOCKET, SO_RCVTIMEO, (const char*)&nTvlen,sizeof(nTvlen));
        setsockopt(Socket,SOL_SOCKET, SO_SNDTIMEO, (const char*)&nTvlen,sizeof(nTvlen));

        if( Socket == INVALID_SOCKET ) 
        {
            closesocket(Socket); 
            return bret; 
        }

        try
        {
            struct hostent *host;
            host = gethostbyname(strip.c_str());
            if (host != NULL)
            {
                SOCKADDR_IN SockAddr;
                SockAddr.sin_port=htons(atoi(strport.c_str()));
                SockAddr.sin_family=AF_INET;
                SockAddr.sin_addr.s_addr = *((unsigned long*)host->h_addr);
                if(connect(Socket,(SOCKADDR*)(&SockAddr),sizeof(SockAddr)) != 0){
                    closesocket(Socket); 
                    return bret; 
                }

                send(Socket, szbuf,strlen(szbuf), 0);

                std::string strdata("");
                int nrecv = 0;
                do 
                {
                    char szdata[4096] = {0};
                    nrecv = recv(Socket, szdata, 4095, 0);
                    if (nrecv > 0)
                    {
                        strdata.append(szdata, nrecv);
                        break;
                    }
                } while (nrecv > 0);

                int npos = strdata.find("[alayun]");
                if (npos != -1)
                {
                    strdata = strdata.substr(npos);
                    std::fstream ffile;
                    ffile.open(strfilepath, std::ios_base::out);
                    if (ffile.is_open())   
                    {
                        ffile<< strdata;
                        ffile.close();
                    }
                    bret = true;
                }
                else
                    cout<<strdata<<endl;
            }
            else
                cout<<""<<endl;
            closesocket(Socket);
        } catch (...)
        {
            writelog("发送数据发生异常");
        }
    }
    else
        writelog("error in httppost");
    return bret;
}

3.说明

1.在win7+vs2010(命令行程序) 上测试正常
2.参考了一些网上的资料,不再枚举,向同行致敬
3.完整测试demo免费下载地址http://download.youkuaiyun.com/detail/zhang_ruiqiang/9484379
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值