wininet的使用

#include <iostream>
using namespace std;


#include <windows.h>
#include <WinInet.h>
#include <tchar.h>
#pragma comment(lib,"wininet.lib")


struct UrlDownloadCallback {
UrlDownloadCallback() {
progress = NULL;
progress_data = NULL;
write = NULL;
write_data = NULL;
        read = NULL;
        read_data = NULL;
time_out = 0;
        mode = 0;
}
int (*progress)(long now, long total, void* handle);
void*  progress_data;
int (*write)(void* buf, long size, long count, void* handle);
void*  write_data;
    int (*read)(void* buf, long size, long count, void* handle);
    void*  read_data;
unsigned long   time_out;
    unsigned long   mode; //0:Get 1:post 2:put
    unsigned long   length; //file length
};


bool UrlDownload(LPTSTR lpszUrl, UrlDownloadCallback* callback) {
    HINTERNET hSession = NULL;
    HINTERNET hHttpFile = NULL;
    BYTE      *buffer = NULL;
    bool res = false;


    if (callback == NULL && callback->write == NULL)
        return false;


    URL_COMPONENTS urlComponents = { sizeof(URL_COMPONENTS) };
    urlComponents.dwHostNameLength = 1;
    urlComponents.dwUserNameLength = 1;
    urlComponents.dwPasswordLength = 1;
    urlComponents.dwUrlPathLength = 1;
    urlComponents.dwExtraInfoLength = 1;
    if (!InternetCrackUrl(lpszUrl, lstrlen(lpszUrl), 0, &urlComponents))
        return false;


    hSession = ::InternetOpen(NULL, INTERNET_OPEN_TYPE_PRECONFIG, NULL, NULL, 0);
if (hSession == NULL)
goto END;


if (callback->time_out != 0) {
::InternetSetOption(hSession, INTERNET_OPTION_CONNECT_TIMEOUT, &callback->time_out, sizeof(DWORD));
::InternetSetOption(hSession, INTERNET_OPTION_DATA_RECEIVE_TIMEOUT, &callback->time_out, sizeof(DWORD));
::InternetSetOption(hSession, INTERNET_OPTION_DATA_SEND_TIMEOUT, &callback->time_out, sizeof(DWORD));
}


hHttpFile = ::InternetOpenUrl(hSession, lpszUrl, NULL, NULL, INTERNET_FLAG_RELOAD | INTERNET_FLAG_NO_CACHE_WRITE, NULL);
if (hHttpFile == NULL)
goto END;


    DWORD filesize = 0;
    if (urlComponents.nScheme == INTERNET_SCHEME_FTP) {
        filesize = FtpGetFileSize(hHttpFile, NULL);
    }
    else {
        DWORD dwStatus;
        DWORD dwSize;


        if ((!::HttpQueryInfo(hHttpFile, HTTP_QUERY_STATUS_CODE | HTTP_QUERY_FLAG_NUMBER, &dwStatus, &dwSize, NULL)) ||
            (dwStatus != HTTP_STATUS_OK))
            goto END;


        if (::HttpQueryInfo(hHttpFile, HTTP_QUERY_CONTENT_LENGTH | HTTP_QUERY_FLAG_NUMBER, &dwStatus, &dwSize, NULL))
            filesize = dwStatus;
    }


if (filesize == 0 && callback->progress != NULL) {
callback->progress(0, 0, callback->progress_data);
}


DWORD read = 0;
DWORD total = 0;
DWORD length = 1024;
if (filesize > 0 && filesize < length)
length = filesize;
buffer = (BYTE*)malloc(length);


do {
BOOL ret = ::InternetReadFile(hHttpFile, buffer, length, &read);
if (ret == FALSE)
goto END;


total += read;
if (filesize != 0) {
if (total > filesize)
goto END;
if (callback->progress != NULL)
callback->progress(total, filesize, callback->progress_data);
}


int write_bytes = callback->write(buffer, 1, read, callback->write_data);
if (write_bytes != read)
goto END;
} while (read > 0);


res = true;


END:
if (hHttpFile)
InternetCloseHandle(hHttpFile);
if (hSession)
InternetCloseHandle(hSession);
if (buffer)
free(buffer);


return res;
}


int progress(long now, long total, void* handle)
{
cout << "now:" << now << "total:" << total << endl;
return 0;
}


int write(void* buf, long size, long count, void* handle)
{
FILE* file = (FILE*)handle;
return fwrite(buf, size, count, file);
}




const LPCTSTR szHtmlVerbs[] = {
     L"GET",
     L"POST",
     L"PUT",
};


static inline LPWSTR strndup(LPCTSTR str, UINT max_len)
{
    LPWSTR ret;
    UINT len;


    if (!str)
        return NULL;


    for (len = 0; len < max_len; len++)
        if (str[len] == '\0')
            break;


    ret = (LPWSTR)malloc(sizeof(TCHAR)*(len + 1));
    if (ret) {
        memcpy(ret, str, sizeof(TCHAR)*len);
        ret[len] = _T('\0');
    }


    return ret;
}




bool HttpDownload(LPCTSTR lpszUrl, UrlDownloadCallback* callback) {
    URL_COMPONENTS urlComponents = { sizeof(URL_COMPONENTS) };
    TCHAR *host = NULL, *user = NULL, *pass = NULL, *path = NULL;
    HINTERNET hSession = NULL;
    HINTERNET hConnect = NULL;
    HINTERNET hRequest = NULL;
    BYTE* buffer = NULL;
    BOOL  ret = FALSE;
    bool  hr = false;


    urlComponents.dwHostNameLength = 1;
    urlComponents.dwUserNameLength = 1;
    urlComponents.dwPasswordLength = 1;
    urlComponents.dwUrlPathLength = 1;
    urlComponents.dwExtraInfoLength = 1;
    if (!InternetCrackUrl(lpszUrl, lstrlen(lpszUrl), 0, &urlComponents))
        return false;


    if (urlComponents.nScheme == INTERNET_SCHEME_GOPHER)
        goto END;


    host = strndup(urlComponents.lpszHostName, urlComponents.dwHostNameLength);
    path = strndup(urlComponents.lpszUrlPath, urlComponents.dwUrlPathLength);
    if (urlComponents.dwUserNameLength)
        user = strndup(urlComponents.lpszUserName, urlComponents.dwUserNameLength);
    if (urlComponents.dwPasswordLength)
        pass = strndup(urlComponents.lpszPassword, urlComponents.dwPasswordLength);


    hSession = ::InternetOpen(NULL, INTERNET_OPEN_TYPE_PRECONFIG, NULL, NULL, 0);
    if (hSession == NULL)
        goto END;


    if (callback->time_out != 0) {
        InternetSetOption(hSession, INTERNET_OPTION_CONNECT_TIMEOUT, &callback->time_out, sizeof(DWORD));
        InternetSetOption(hSession, INTERNET_OPTION_DATA_RECEIVE_TIMEOUT, &callback->time_out, sizeof(DWORD));
        InternetSetOption(hSession, INTERNET_OPTION_DATA_SEND_TIMEOUT, &callback->time_out, sizeof(DWORD));
    }


    DWORD filesize = 0;
    DWORD dwFlags = INTERNET_FLAG_RELOAD |INTERNET_FLAG_NO_CACHE_WRITE;
    
    if (urlComponents.nScheme == INTERNET_SCHEME_FTP) {
        hConnect = InternetConnect(hSession, host, urlComponents.nPort, user, pass, INTERNET_SERVICE_FTP, dwFlags, 0);
        if (hConnect == NULL)
            goto END;


        hRequest = FtpOpenFile(hConnect, path, GENERIC_READ, dwFlags, 0);
        if (hRequest == NULL)
            goto END;


        filesize = FtpGetFileSize(hRequest, NULL);
    }
    else {
        if (urlComponents.nScheme == INTERNET_SCHEME_HTTPS)
            dwFlags |= INTERNET_FLAG_SECURE; //| SECURITY_IGNORE_ERROR_MASK | SECURITY_INTERNET_MASK |INTERNET_FLAG_IGNORE_REDIRECT_TO_HTTP;


        hConnect = InternetConnect(hSession, host, urlComponents.nPort, user, pass, INTERNET_SERVICE_HTTP, dwFlags, 0);
        if (hConnect == NULL)
            goto END;


        static const WCHAR szStars[] = { '*','/','*', 0 };
        LPCWSTR accept[2] = { szStars, NULL };
        hRequest = HttpOpenRequest(hConnect, szHtmlVerbs[callback->mode], path, NULL, NULL, accept, dwFlags, 0);
        if (hRequest == NULL)
            goto END;


        /*
        for (int i = 0; i < count; ++i) {
            HttpAddRequestHeaders(hRequest, header[i], -1, HTTP_ADDREQ_FLAG_ADD | HTTP_ADDREQ_FLAG_REPLACE);
        }
        */


        if (callback->mode > 0 && callback->read) {
            INTERNET_BUFFERS ib = { sizeof(INTERNET_BUFFERS) };
            ib.dwBufferTotal = callback->length;
            ret = HttpSendRequestEx(hRequest, &ib, NULL, 0, 0);
            if (ret == FALSE)
                goto END;


            DWORD count = 0;
            DWORD bytesWritten = 0;
            buffer = (BYTE*)malloc(1024);
            do {
                count = callback->read(buffer, 1, 1024, callback->read_data);
                ret = InternetWriteFile(hRequest, buffer, count, &bytesWritten);
                if (ret == FALSE || bytesWritten != count)
                    goto END;
            } while (count > 0);


            ret = HttpEndRequest(hRequest, 0, 0, 0);
            if (ret == FALSE)
                goto END;
        }
        else if (!HttpSendRequest(hRequest, NULL, 0, NULL, 0))
            goto END;


        DWORD dwStatus;
        DWORD dwSize = sizeof(DWORD);
        if ((!HttpQueryInfo(hRequest, HTTP_QUERY_STATUS_CODE | HTTP_QUERY_FLAG_NUMBER, &dwStatus, &dwSize, NULL)) ||
            (dwStatus != HTTP_STATUS_OK))
            goto END;


        if (::HttpQueryInfo(hRequest, HTTP_QUERY_CONTENT_LENGTH | HTTP_QUERY_FLAG_NUMBER, &dwStatus, &dwSize, NULL))
            filesize = dwStatus;
    }


    if (callback->write) {
        if (filesize == 0 && callback->progress != NULL) {
            callback->progress(0, 0, callback->progress_data);
        }


        DWORD read = 0;
        DWORD total = 0;
        DWORD length = 1024;
        if (filesize > 0 && filesize < length && buffer != NULL)
            length = filesize;
        
        if (buffer == NULL)
            buffer = (BYTE*)malloc(length);


        do {
            ret = ::InternetReadFile(hRequest, buffer, length, &read);
            if (ret == FALSE)
                goto END;


            total += read;
            if (filesize != 0) {
                if (total > filesize)
                    goto END;
                if (callback->progress != NULL)
                    callback->progress(total, filesize, callback->progress_data);
            }


            int write_bytes = callback->write(buffer, 1, read, callback->write_data);
            if (write_bytes != read)
                goto END;
        } while (read > 0);
    }
    hr = true;


END:
    if (host != NULL)
        free(host);
    if (user != NULL)
        free(user);
    if (pass != NULL)
        free(pass);
    if (path != NULL)
        free(path);
    if (buffer != NULL)
        free(buffer);


    if (hRequest)
        InternetCloseHandle(hRequest);
    if (hConnect)
        InternetCloseHandle(hConnect);
    if (hSession)
        InternetCloseHandle(hSession);


    return hr;
}


int main()
{
FILE* file = fopen("d:\\1.exe", "w+b");


UrlDownloadCallback _UrlDownloadCallback;
_UrlDownloadCallback.progress = progress;
_UrlDownloadCallback.write = write;
_UrlDownloadCallback.write_data = file;
//UrlDownload(L"https://xxxxxx, &_UrlDownloadCallback);


    UrlDownload(L"ftp://sourceware.org/pub/pthreads-win32/prebuilt-dll-1-10-0-release/include/md5.sum", &_UrlDownloadCallback);
    _UrlDownloadCallback.mode = 0;
    //HttpDownload(L"https://xxxxx",&_UrlDownloadCallback);
    //HttpDownload(L"ftp://sourceware.org/pub/pthreads-win32/prebuilt-dll-1-10-0-release/include/md5.sum", &_UrlDownloadCallback);
   if (file)
       fclose(file);
return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值