由于软件里面需要一个下载功能, 就从<C++编程艺术>里面把代码搞出来, 做了一个Unicode版本的下载功能(为了跟软件和谐一点点..).
原理挺简单的, 基本就是用WinINet里面的函数, 详细的就不说了.
对于ANSI版本的字符串函数对应的Unicode版本, 可以参见这个链接.
推荐一下<C++编程艺术>这本书, 虽然很基础..
还是上代码吧~~
1 //dl.h 2 #include <iostream> 3 #include <windows.h> 4 #include <wininet.h> 5 #include <fstream> 6 #include <cstdio> 7 8 using namespace std; 9 10 const int MAX_ERRMSG_SIZE = 80; 11 const int MAX_FILENAME_SIZE = 512; 12 const int BUF_SIZE = 1024; 13 14 // A class for downloading files from the Internet. 15 class Download 16 { 17 public: 18 static bool ishttp(TCHAR *url); 19 static bool httpverOK(HINTERNET hIurl); 20 static bool getfname(TCHAR *url, TCHAR *fname); 21 static unsigned long openfile(TCHAR *url, bool reload, 22 ofstream &fout); 23 public: 24 static bool download(TCHAR *url, bool restart = false, 25 void (*update)(unsigned long, unsigned long) = NULL); 26 }; 27 28 //dl.cpp 29 #include "dl.h" 30 #include <tchar.h> 31 32 bool Download::download(TCHAR *url, bool reload, 33 void (*update)(unsigned long, unsigned long)) 34 { 35 ofstream fout; // output stream 36 unsigned char buf[BUF_SIZE]; // input buffer 37 unsigned long numrcved; // number of bytes read 38 unsigned long filelen; // length of file on disk 39 HINTERNET hIurl, hInet; // Internet handles 40 unsigned long contentlen;// length of content 41 unsigned long len; // length of contentlen 42 unsigned long total = 0; // running total of bytes received 43 TCHAR header[80]; // holds Range header 44 45 if(!ishttp(url)) 46 return FALSE; 47 48 filelen = openfile(url, reload, fout); 49 50 // See if Internet connection available. 51 if(InternetAttemptConnect(0) != ERROR_SUCCESS) 52 { 53 return FALSE; 54 } 55 56 // Open Internet connection. 57 hInet = InternetOpen(TEXT("downloader"), 58 INTERNET_OPEN_TYPE_DIRECT, 59 NULL, NULL, 0); 60 61 if(hInet == NULL)return FALSE; 62 63 // Construct header requesting range of data. 64 swprintf(header, TEXT("Range:bytes=%d-"), filelen); 65 /*printf("%s\n", header);*/ 66 67 // Open the URL and request range. 68 hIurl = InternetOpenUrl(hInet, url, 69 header, -1, 70 INTERNET_FLAG_NO_CACHE_WRITE, 0); 71 72 if(hIurl == NULL) 73 { 74 return FALSE; 75 } 76 77 // Confirm that HTTP/1.1 or greater is supported. 78 if(!httpverOK(hIurl)) 79 return FALSE; 80 81 // Get content length. 82 len = sizeof(contentlen); 83 if(!HttpQueryInfo(hIurl, 84 HTTP_QUERY_CONTENT_LENGTH | 85 HTTP_QUERY_FLAG_NUMBER, 86 &contentlen, &len, NULL)) 87 { 88 89 printf("File or content length not found.\n"); 90 } 91 92 // If existing file (if any) is not complete, 93 // then finish downloading. 94 if(filelen != contentlen && contentlen) 95 do 96 { 97 // Read a buffer of info. 98 if(!InternetReadFile(hIurl, &buf, 99 BUF_SIZE, &numrcved)) 100 { 101 printf("Error occurred during download.\n"); 102 } 103 104 // Write buffer to disk. 105 fout.write((const char *) buf, numrcved); 106 if(!fout.good()) 107 { 108 printf("Error writing file.\n"); 109 } 110 111 total += numrcved; // update running total 112 113 // Call update function, if specified. 114 if(update && numrcved > 0) 115 update(contentlen + filelen, total + filelen); 116 117 } 118 while(numrcved > 0); 119 else if(update) 120 update(filelen, filelen); 121 122 fout.close(); 123 InternetCloseHandle(hIurl); 124 InternetCloseHandle(hInet); 125 126 return true; 127 } 128 129 // Return true if HTTP version of 1.1 or greater. 130 bool Download::httpverOK(HINTERNET hIurl) 131 { 132 TCHAR str[80] = {0}; 133 unsigned long len = 79; 134 135 // Get HTTP version. 136 if(!HttpQueryInfo(hIurl, HTTP_QUERY_VERSION, &str, &len, NULL)) 137 return false; 138 TCHAR *p = wcschr(str, TEXT('/')); 139 140 p++; 141 if(*p == TEXT('0')) return false; // can use HTTP 0.x 142 143 // Now, find start of minor HTTP version number. 144 p = wcschr(str, TEXT('.')); 145 p++; 146 147 // Convert to int. 148 int minorVerNum = _tstoi(p); 149 150 if(minorVerNum > 0) return true; 151 return false; 152 } 153 154 // Extract the filename from the URL. Return false if 155 // the filename cannot be found. 156 bool Download::getfname(TCHAR *url, TCHAR *fname) 157 { 158 TCHAR *p = wcsrchr(url, TEXT('/')); 159 if(p && (wcslen(p) < MAX_FILENAME_SIZE)) 160 { 161 p++; 162 wcscpy(fname, p); 163 return true; 164 } 165 else 166 return false; 167 } 168 169 //返回的值是文件的大小, 用户后来展现进度用... 170 unsigned long Download::openfile(TCHAR *url, 171 bool reload, 172 ofstream &fout) 173 { 174 TCHAR fname[MAX_FILENAME_SIZE]; 175 176 if(!getfname(url, fname)) 177 return 0; 178 if(!reload) 179 fout.open(fname, ios::binary | ios::out | 180 ios::app | ios::ate); 181 else 182 fout.open(fname, ios::binary | ios::out | 183 ios::trunc); 184 if(!fout) 185 return 0; 186 return fout.tellp(); 187 } 188 189 bool Download::ishttp(TCHAR *url) 190 { 191 TCHAR str[5] = TEXT(""); 192 wcsncpy(str, url, 4); 193 for(TCHAR *p = str; *p; p++) *p = towlower(*p); 194 return !wcscmp(TEXT("http"), str); 195 } 196 197 //main.cpp 198 #include <iostream> 199 #include "dl.h" 200 201 // This function displays the download progress as a percentage. 202 void showprogress(unsigned long total, unsigned long part) 203 { 204 int val = (int) ((double) part / total * 100); 205 cout << val << "%" << endl; 206 } 207 208 int main(int argc, char *argv[]) 209 { 210 TCHAR url[] = 211 TEXT("http://zeq2.com/SVN/Source/Tools/MinGW/include/ddk/ntddk.h"); 212 213 bool reload = false; 214 215 if(argc == 2 && !strcmp(argv[1], "reload")) 216 reload = true; 217 218 cout << "Beginning download.\n"; 219 if(Download::download(url, reload, showprogress)) 220 cout << "Download Complete\n"; 221 return 0; 222 }