现在的位置: 首页 > 自动控制 > 工业·编程 > 正文

C++ wininet和winsock下载文件

2013-03-26 06:35 工业·编程 ⁄ 共 12270字 ⁄ 字号 暂无评论

1.winnet方式

(如果在VS05或VS08中编译,需要设置:项目-》属性-》配置属性-》常规-》字符集-》如果是Unicode,则设置成“使用多字节字符集”)

CVodStreamCache.h

 
#ifndef _CVodStreamCache_H
#define _CVodStreamCache_H
 
#include
#include
#include
#include
#include
using namespace std;
 
#pragma comment(lib, "wininet.lib")
 
 
class CVodStreamCache
{
public:
    HANDLE Create(char token[], char path[]);
    int ReadBlock(long offset, int len, char *buffer);
    int WriteBlock();
    void Destory();
    void CacheInfo();
protected:
private:
    HINTERNET internetOpen;
    HINTERNET internetOpenUrl;
 
    DWORD dwStatusCode;
    DWORD dwContentLength;
 
    HANDLE createFile;
    static const int BUFFERSIZE = 1024;
};
 
 
#endif
CVodStreamCache.cpp

 
#include "CVodStreamCache.h"
 
HANDLE CVodStreamCache::Create(char token[], char path[])
{
    internetOpen = InternetOpen(NULL, INTERNET_OPEN_TYPE_DIRECT, NULL, NULL, 0);
    if (internetOpen == NULL)
    {
        cout << "Internet open failed!" << endl;
        return NULL;
    }
 
    //LPCTSTR p = TEXT(path);
    internetOpenUrl = InternetOpenUrl(internetOpen, path,
        NULL, 0, INTERNET_FLAG_TRANSFER_BINARY | INTERNET_FLAG_PRAGMA_NOCACHE, 0);
    if (internetOpenUrl == NULL)
    {
        cout << "Internet open url failed! Error code = " << GetLastError() << endl;
        InternetCloseHandle(internetOpen);
        return NULL;
    }
 
    DWORD dwStatusSize = sizeof(dwStatusCode);
    HttpQueryInfo(internetOpenUrl, HTTP_QUERY_STATUS_CODE|HTTP_QUERY_FLAG_NUMBER, &dwStatusCode, &dwStatusSize, NULL);
    cout << "Status: " << dwStatusCode << endl;
 
    DWORD dwLengthSize = sizeof(dwContentLength);
    HttpQueryInfo(internetOpenUrl, HTTP_QUERY_CONTENT_LENGTH|HTTP_QUERY_FLAG_NUMBER, &dwContentLength, &dwLengthSize, NULL);
    cout << "File size: " << dwContentLength << endl;
 
    createFile = CreateFile(_T("E://download.jpg"), GENERIC_WRITE|GENERIC_READ, 0, 0, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, 0);
    if (createFile == INVALID_HANDLE_VALUE)
    {
        cout << "Create file failed!" << endl;
        InternetCloseHandle(internetOpenUrl);
        return NULL;
    }
 
    return createFile;
}
 
int CVodStreamCache::ReadBlock(long offset, int len, char *buffer)
{
    return 0;
}
 
int CVodStreamCache::WriteBlock()
{
    BOOL internetReadFile;
    char buffer[BUFFERSIZE];
    memset(buffer, 0, sizeof(buffer));
    DWORD byteRead = 0;
 
    BOOL hwrite;
    DWORD written;
 
    DWORD byteDown = 0;
    int a = 0;
    cout << "已下载:" << a << "%";
    while (1)
    {
        internetReadFile = InternetReadFile(internetOpenUrl, buffer, sizeof(buffer), &byteRead);
        if (byteRead == 0)
        {
            break;
        }
 
        byteDown += byteRead;
        cout << "/b";
        do
        {
            cout << "/b";
            a /= 10;
        } while (a);
        a = 100 * byteDown / dwContentLength;
        cout << a << "%";
 
        //SetFilePointer(createFile, a, NULL, FILE_BEGIN);
        hwrite = WriteFile(createFile, buffer, sizeof(buffer), &written, NULL);
        if (hwrite == 0)
        {
            cout << "Write to file failed!" << endl;
            CloseHandle(createFile);
            return 0;
        }
        //FlushFileBuffers(createFile);
    }
 
    cout << endl << "Finished downloading!" << endl;
 
    return 1;
}
 
void CVodStreamCache::Destory()
{
    ;
}
 
void CVodStreamCache::CacheInfo()
{
    ;
}
 
int main()
{
    CVodStreamCache vsc;
    vsc.Create("", "http://avatar.profile.csdn.net/0/2/6/2_ice_gream.jpg");
    vsc.WriteBlock();
 
    return 0;
}

2.winsock方式

CVodStreamCache.h

 
#ifndef CVodStreamCache_H_
#define CVodStreamCache_H_
 
#include
#include
#include
#pragma comment(lib, "ws2_32.lib")
using namespace std;
 
 
class Cache
{
public:
    Cache();
    ~Cache();
    void setTotalLen(long totalLen);
    void setRecvLen(long recvLen);
    long getTotalLen();
    long getRecvLen();
 
protected:
 
private:
    char *filename;
    long totalLen;
    long recvLen;
 
};
 
 
class CVodStreamCache
{
public:
    CVodStreamCache();
    ~CVodStreamCache();
 
    HANDLE Create(char token[], char path[]);
    int ReadBlock(long offset, int len, char *buff);
    int WriteBlock(long offset, int len, char *buff);
    void Destroy();
    void CacheInfo();    // 获取缓存信息,状态等等
 
    void InitSocketLib();    // 初始化Socket函数库
    void ParseURL(char* url);    // 解析URL地址
    void FormatRequestHeader(char* pHost, char* pGet, long lFrom=0, long lTo=0);    // 格式化请求头
    void Socket();    // 创建SOCKET对象
    void Connect(char* pHost, int port=80);    // 建立连接
    void SendRequest(const char* requestHeader);    // 发送请求头
    void GetResponseHeader();    // 获取完整的返回头
    void SetTimeOut(int nTime, int type=0);    // 设置接收或发送的最长时间
    void InitCache();    // 初始化Cache,获取文件长度
 
protected:
 
private:
    BOOL err;
    char *pHost;    // 主机地址
    char *pGet;    // GET 相对路径
    char *requestHeader;    // 请求头
    SOCKET sock;
    char *responseHeader;    // 回应头
    fstream cacheFile;    // 输入输出文件流
 
    Cache cache;
 
};
 
 
#endif
CVodStreamCache.cpp

 
#include "CVodStreamCache.h"
 
// constructor
CVodStreamCache::CVodStreamCache()
{
    err = FALSE;
    pHost = NULL;
    pGet = NULL;
    requestHeader = NULL;
    responseHeader = NULL;
}
 
// destructor
CVodStreamCache::~CVodStreamCache()
{
    ;
}
 
HANDLE CVodStreamCache::Create(char token[], char path[])
{
    // 出错了
    if (err)
    {
        return NULL;
    }
 
    InitSocketLib();    // 初始化Socket函数库
    ParseURL(path);    // 解析URL地址
    Socket();    // 创建SOCKET对象
    Connect(pHost);    // 建立连接
 
    FormatRequestHeader(pHost, pGet);    // 格式化请求头
    SendRequest(requestHeader);    // 发送请求头
    GetResponseHeader();    // 获取完整的返回头
    SetTimeOut(10000);    // 设置接收或发送的最长时间
    InitCache();    // 初始化Cache,获取文件长度
 
    // 创建指定大小的文件
    cacheFile.open("E://zz.txt", ios::binary|ios::out);
    for (int i=0; i<cache.getTotalLen(); ++i)
    {
        cacheFile.put('/0');
    }
    cacheFile.close();
 
    if (err)
    {
        cout << "创建失败!" << endl;
    }
    else
    {
        cout << "创建成功!" << endl;
    }
 
    return NULL;
}
 
int CVodStreamCache::ReadBlock(long offset, int len, char *buff)
{
    cacheFile.open("E://zz.txt", ios::binary|ios::in);
    if (!cacheFile)
    {
        cout << "cannot open file!" << endl;
    }
    int rcv_bytes = 0;
    cacheFile.seekg(offset, ios::beg);
    cacheFile.read(buff, len);
    rcv_bytes = cacheFile.gcount();
    cacheFile.close();
    return rcv_bytes;
}
 
int CVodStreamCache::WriteBlock(long offset, int len, char *buff)
{
    FormatRequestHeader(pHost, pGet, offset, offset+len-1);    // 格式化请求头
    SendRequest(requestHeader);    // 发送请求头
    //GetResponseHeader();    // 获取完整的返回头
    //SetTimeOut(5000);    // 设置接收或发送的最长时间
 
    cacheFile.open("E://zz.txt", ios::binary|ios::in|ios::out);
    if (!cacheFile)
    {
        cout << "cannot open file" << endl;
    }
    int rcv_bytes = 0;
    rcv_bytes = recv(sock, buff, len, 0);
   
    if (rcv_bytes > 0)
    {
        cacheFile.seekp(offset, ios::beg);
        cacheFile.write(buff, rcv_bytes);
        cache.setRecvLen(cache.getRecvLen()+len);
    }
    cacheFile.close();
    return rcv_bytes;
}
 
void CVodStreamCache::Destroy()
{
    if (!err)
    {
        //delete[] pHost;
 
        closesocket(sock);
    }
    WSACleanup();
}
 
void CVodStreamCache::CacheInfo()
{
    ;
}
 
// 初始化Socket函数库
void CVodStreamCache::InitSocketLib()
{
    if (err) return;
 
    WORD wVersion;
    WSADATA wsaData;
 
    wVersion = MAKEWORD(2, 0);
    if (WSAStartup(wVersion, &wsaData) != 0)
    {
        cout << "无法装载Socket库!" << endl;
        err = FALSE;
        return;
    }
    if (LOBYTE(wsaData.wVersion) != 2)
    {
        cout << "无法找到合适的Socket库!" << endl;
        err = FALSE;
        WSACleanup();
        return;
    }
}
 
// 解析URL地址
void CVodStreamCache::ParseURL(char* url)
{
    if (err) return;
 
    pHost = new char[strlen(url)];
    strcpy(pHost, url);
    for (int i=0; i<strlen(pHost); ++i)
    {
        if (pHost[i]=='/' || pHost[i]=='/0')
        {
            pHost[i] = '/0';
            break;
        }
        ++url;
    }
 
    pGet = new char[strlen(url)+1];
    if (*url == '/0')
    {
        strcpy(pGet, "/");
    }
    else
    {
        strcpy(pGet, url);
    }
}
 
// 根据URL输出HTTP请求头
void CVodStreamCache::FormatRequestHeader(char* pHost, char* pGet, long lFrom/* =0 */, long lTo/* =0 */)
{
    if (err) return;
 
    if (requestHeader != NULL)
    {
        delete[] requestHeader;
        requestHeader = NULL;
    }
 
    requestHeader = new char[1024];
    memset(requestHeader, 0, sizeof(requestHeader));
 
    // 方法,请求的路径,版本
    strcat(requestHeader, "GET ");
    strcat(requestHeader, pGet);
    strcat(requestHeader, " HTTP/1.1");
    strcat(requestHeader, "/r/n");
 
    // 主机
    strcat(requestHeader, "Host: ");
    strcat(requestHeader, pHost);
    strcat(requestHeader, "/r/n");
 
    /*if(pReferer != NULL)
    {
        strcat(requestHeader, "Referer:");
        strcat(requestHeader, pReferer);
        strcat(requestHeader, "/r/n");       
    }*/
 
    // 接收的数据类型
    strcat(requestHeader, "Accept:*/*");
    strcat(requestHeader, "/r/n");
 
    // 浏览器类型
    strcat(requestHeader, "User-Agent:Mozilla/4.0 (compatible; MSIE 5.00; Windows 98)");
    strcat(requestHeader, "/r/n");
 
    // 连接设置,保持
    strcat(requestHeader, "Connection:Keep-Alive");
    strcat(requestHeader, "/r/n");
 
    // Cookie
    /*if(pCookie != NULL)
    {
        strcat(requestHeader, "Set Cookie:0");
        strcat(requestHeader, pCookie);
        strcat(requestHeader, "/r/n");
    }*/
 
    // 请求的数据起始字节位置(断点续传的关键)
    if (lFrom > 0)
    {
        char temp[10];
 
        strcat(requestHeader, "Range: bytes=");
        _ltoa(lFrom, temp, sizeof(temp));
        strcat(requestHeader, temp);
        strcat(requestHeader, "-");
 
        if (lTo > lFrom)
        {
            _ltoa(lTo, temp, sizeof(temp));
            strcat(requestHeader, temp);
        }
        strcat(requestHeader, "/r/n");
    }
 
    // 最后一行:空行
    strcat(requestHeader, "/r/n");
 
    cout << endl << "发送的请求头为:" << endl << requestHeader;
}
 
// 创建SOCKET对象
void CVodStreamCache::Socket()
{
    if (err) return;
 
    struct protoent *ppe;
    ppe=getprotobyname("tcp");
 
    sock = socket(PF_INET, SOCK_STREAM, ppe->p_proto);
    if (sock == INVALID_SOCKET)
    {
        cout << "创建Socket对象失败!" << endl;
        err = TRUE;
        return;
    }
}
 
// 建立连接
void CVodStreamCache::Connect(char* pHost, int port/* =80 */)
{
    if (err) return;
 
    // 根据主机名获取IP地址
    hostent* pHostEnt = gethostbyname(pHost);
    if (pHostEnt == NULL)
    {
        cout << "获取IP地址失败!" << endl;
        err = TRUE;
        return;
    }
 
    // 连接
    struct in_addr ip_addr;
    memcpy(&ip_addr, pHostEnt->h_addr_list[0], 4);    // h_addr_list[0]里4个字节,每个字节8位
 
    struct sockaddr_in destaddr;
    memset((void*)&destaddr, 0, sizeof(destaddr));
    destaddr.sin_family = AF_INET;
    destaddr.sin_port = htons(port);
    destaddr.sin_addr = ip_addr;
 
    if (0 != connect(sock, (struct sockaddr*)&destaddr, sizeof(destaddr)))
    {
        cout << "连接失败!" << endl;
        err = TRUE;
        return;
    }
}
 
// 发送请求头
void CVodStreamCache::SendRequest(const char* requestHeader)
{
    if (err) return;
 
    if (SOCKET_ERROR == send(sock, requestHeader, strlen(requestHeader), 0))
    {
        cout << "请求头发送失败!" << endl;
        err = TRUE;
        return;
    }
}
 
// 获取完整的返回头
void CVodStreamCache::GetResponseHeader()
{
    if (err) return;
 
    if (responseHeader != NULL)
    {
        delete[] responseHeader;
        responseHeader = NULL;
    }
 
    responseHeader = new char[1024];
    memset(responseHeader, 0, sizeof(responseHeader));
    char c;
    int i = 0;
    while (1)
    {
        recv(sock, &c, 1, 0);
        responseHeader[i++] = c;
        if (i >= 4)
        {
            if (responseHeader[i-4]=='/r' && responseHeader[i-3]=='/n' &&
                responseHeader[i-2]=='/r' && responseHeader[i-1]=='/n')
            {
                break;
            }
        }
    }
    responseHeader[i] = '/0';
 
    cout << "接收的回应头为:" << endl << responseHeader << endl;
}
 
// 设置接收或发送的最长时间
void CVodStreamCache::SetTimeOut(int nTime, int type/* =0 */)
{
    if (err) return;
 
    if (type == 0)
    {
        type = SO_RCVTIMEO;
    }
    else
    {
        type = SO_SNDTIMEO;
    }
 
    if (setsockopt(sock, SOL_SOCKET, type, (char*)&nTime, sizeof(nTime)) != 0)
    {
        cout << "设置失败!" << endl;
        err = TRUE;
        return;
    }
}
 
// 初始化Cache,获取文件长度
void CVodStreamCache::InitCache()
{
    if (err) return;
 
    char *pos;
    char strResponse[] = "Content-Length";
    pos = strstr(responseHeader, strResponse);
    pos += (strlen(strResponse) + 2);
 
    long len = 0;
    while (*pos != '/r')
    {
        len = len * 10 + *pos - 48;
        ++pos;
    }
 
    cache.setTotalLen(len);
    cache.setRecvLen(0);
}
Cache.cpp

 
#include "CVodStreamCache.h"
 
Cache::Cache()
{
    filename = NULL;
    totalLen = 0;
    recvLen = 0;
}
 
Cache::~Cache()
{
    ;
}
 
void Cache::setTotalLen(long totalLen)
{
    this->totalLen = totalLen;
}
 
void Cache::setRecvLen(long recvLen)
{
    this->recvLen = recvLen;
}
 
long Cache::getTotalLen()
{
    return totalLen;
}
 
long Cache::getRecvLen()
{
    return recvLen;
}
Test.cpp

 
#include "CVodStreamCache.h"
#include
 
int main()
{
    CVodStreamCache vsc;
    vsc.Create("", "www.vijaymukhi.com/vmis/olec.txt");
 
    int rcv_bytes, i=0;
    char buff[1025];
    /*while (1)
    {
        rcv_bytes = vsc.WriteBlock(i, 1024, buff);
        if (rcv_bytes <= 0)
        {
            break;
        }
        i += rcv_bytes;
        system("pause");
    }*/
    vsc.WriteBlock(1024, 1024, buff);
    vsc.WriteBlock(0, 1024, buff);
    vsc.WriteBlock(2048, 1024, buff);
 
    vsc.Destroy();
 
 
    /*CVodStreamCache vsc;
    int rcv_bytes, i=0;
    char buff[1025];
    while (1)
    {
        rcv_bytes = vsc.ReadBlock(i, 1024, buff);
        if (rcv_bytes <= 0)
        {
            break;
        }
        cout << rcv_bytes << endl;
        cout << buff << endl;
        i += rcv_bytes;
        system("pause");
    }*/
 
    cout << "Hello,world" << endl;
    return 0;
}

给我留言

留言无头像?