Jackiesteed

www.github.com/jackiesteed

  博客园  :: 首页  :: 新随笔  :: 联系 :: 订阅 订阅  :: 管理

由于软件里面需要一个下载功能, 就从<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 }
posted on 2012-11-02 22:04  Jackiesteed  阅读(891)  评论(0编辑  收藏  举报