NDK开发中的一个HTTP下载实例附带下载进度
有一个控制下载的管理类吧,调用http下载类进行各种下载,同时在下载过程中可以显示其下载的进度,而且在每个下载结束之后以类似回调的方式告诉管理类,以继续进行后续的操作。
直接代码:
.h文件
1 #pragma once
2 #include <stdio.h>
3 #include <sys/types.h>
4 #include <sys/socket.h>
5 #include <netinet/in.h>
6 #include <netdb.h>
7 #include <stdlib.h>
8 #include <iostream>
9 #include <string.h>
10 #include <unistd.h>
11 #include <fstream>
12 #include <vector>
13 #include <pthread.h>
14 #include <android/log.h>
15 using namespace std;
16
17
18 class CHttpDownLoad
19 {
20 public:
21 CHttpDownLoad(void);
22 ~CHttpDownLoad(void);
23
24 public:
25 void DownLoad(string str1,string str2,string str3,void* handler);
26 int GetDownState();
27 private:
28 int GetFileSize(const char* host,const char* file,string* error,int& headersize);
29
30
31 public:
32 string m_strIP;
33 string m_strFileName;
34 string m_strLocFile ;
35 float m_filesize ;
36 int m_hsize;
37 int m_iProgress;
38 void *m_pUdateBase;
39 };
.cpp文件
1 #include "stdafx.h"
2 #include "CHttpDownLoad.h"
3 #include <stdlib.h>
4 #include "updateBase.h"
5
6 typedef string::size_type (string::*find_t)(const string& delim,string::size_type offset) const;
7
8 vector<string> Split(const string& s,const string& match,bool removeEmpty=false,bool fullMatch=false)
9 {
10 vector<string> result;
11 string::size_type start = 0, skip = 1;
12 find_t pfind = &string::find_first_of;
13 if (fullMatch)
14 {
15 skip = match.length();
16 pfind = &string::find;
17 }
18 while (start != string::npos)
19 {
20 string::size_type end = (s.*pfind)(match, start);
21 if (skip == 0) end = string::npos;
22 string token = s.substr(start, end - start);
23 if (!(removeEmpty && token.empty()))
24 {
25 result.push_back(token);
26 }
27 if ((start = end) != string::npos) start += skip;
28 }
29
30 return result;
31 }
32
33 void SplitProperty(vector<string> property,string* name,string *value)
34 {
35 vector<string>::iterator it=property.begin();
36 if(it!= property.end())
37 {
38 name->clear();
39 name->append(*it);
40 }
41 it++;
42 if(it!= property.end())
43 {
44 value->clear();
45 value->append(*it);
46 }
47 }
48
49
50 CHttpDownLoad::CHttpDownLoad(void)
51 {
52 m_filesize = 0;
53 m_hsize = 0;
54 m_iProgress = 0;
55 m_pUdateBase = NULL;
56 }
57
58
59 CHttpDownLoad::~CHttpDownLoad(void)
60 {
61 }
62
63 void DownloadFile(const char* host,
64 const char* file,
65 const char * savefile,
66 float size,int hsize,
67 int& progress,
68 updateBase* handler
69 )
70 {
71 struct sockaddr_in servaddr;
72 struct hostent *hp;
73 string info;
74 int sock_id;
75 //char message[18000] = {0};
76 char *message = new char[18000];
77 memset(message,0,18000);
78 //char messagetop[18000]={0};
79 char *messagetop = new char[18000];
80 memset(messagetop,0,18000);
81 int msglen;
82 float readcount=0;
83 string request;
84 request.append("GET ");
85 request.append(file);
86 request.append(" HTTP/1.1\n");
87 request.append("Host:");
88 request.append(host);
89 request.append("\r\n\r\n");
90 if((sock_id = socket(AF_INET, SOCK_STREAM, 0)) == -1)
91 {
92 return;
93 }
94 memset(&servaddr,0,sizeof(servaddr));
95 if((hp = gethostbyname(host)) == NULL)
96 {
97 return;
98 }
99 memcpy((char *)&servaddr.sin_addr.s_addr, (char *)hp->h_addr, hp->h_length);
100 servaddr.sin_port = htons(80);
101 servaddr.sin_family = AF_INET;
102 if(connect(sock_id, (struct sockaddr *)&servaddr, sizeof(servaddr)) != 0)
103 {
104 return;
105 }
106 write(sock_id,request.c_str(),request.length());
107 ofstream outfile (savefile,ofstream::binary);
108 do{
109 msglen = read(sock_id,message,18000);
110 if(msglen==0)
111 {
112 break;
113 }
114
115 if(readcount==0)
116 {
117 int tempindex=0;
118 //for(int i =hsize - 1;i<msglen;i++)
119 for(int i =hsize;i<msglen;i++)
120 {
121 messagetop[tempindex]= message[i];
122 tempindex=tempindex+1;
123 }
124 outfile.write (messagetop,tempindex);
125 }
126 else
127 {
128 outfile.write (message,msglen);
129 }
130 readcount=readcount+msglen;
131 progress = readcount/size*100;
132 }while(readcount<=(size+ hsize));
133 outfile.close();
134 close(sock_id);
135
136 if (message != NULL)
137 {
138 delete[] message;
139 message = NULL;
140 }
141 if (messagetop != NULL)
142 {
143 delete[] messagetop;
144 messagetop = NULL;
145 }
146
147 handler->CallupdateBaseFinsh();//回调下载结束
148
149 }
150
151 void* UpdateWorCoping(void* data)
152 {
153 CHttpDownLoad *pGhttpFile = (CHttpDownLoad*)data;
154 DownloadFile(pGhttpFile->m_strIP.c_str(),
155 pGhttpFile->m_strFileName.c_str(),
156 pGhttpFile->m_strLocFile.c_str(),
157 pGhttpFile->m_filesize,
158 pGhttpFile->m_hsize,
159 pGhttpFile->m_iProgress,
160 (updateBase*)pGhttpFile->m_pUdateBase
161 );
162
163 return ((void*)0);
164 }
165
166 int CHttpDownLoad::GetFileSize(const char* host,const char* file,string* error,int& headersize)
167 {
168 int size=-1;
169 struct sockaddr_in servaddr;
170 struct hostent *hp;
171 string splitline="\r\n";
172 string PName;
173 string PValue;
174 string splittagbalue=":";
175 string info;
176 vector<string> properties;
177 vector<string> property;
178 int sock_id;
179 //char message[1024*1024] = {0};
180 char *message = new char[1024*1024];
181 memset(message,0,1024*1024);
182 int msglen;
183 string request;
184 request.append("HEAD ");
185 request.append(file);
186 request.append(" HTTP/1.1\n");
187 request.append("Host:");
188 request.append(host);
189 request.append("\r\n\r\n");
190 if((sock_id = socket(AF_INET, SOCK_STREAM, 0)) == -1)
191 {
192 error->append("Couldn't get a socket!");
193 return size;
194 }
195 memset(&servaddr,0,sizeof(servaddr));
196
197 if((hp = gethostbyname(host)) == NULL)
198 {
199 error->append("Couldn't access network.");
200 error->append(host);
201 return size;
202 }
203 memcpy((char *)&servaddr.sin_addr.s_addr, (char *)hp->h_addr, hp->h_length);
204 servaddr.sin_port = htons(80);
205 servaddr.sin_family = AF_INET;
206 if(connect(sock_id, (struct sockaddr *)&servaddr, sizeof(servaddr)) != 0)
207 {
208 error->append("Couldn't connect!");
209 return size;
210 }
211 write(sock_id,request.c_str(),request.length());
212 msglen = read(sock_id,message,1024*1024);
213 headersize= msglen;
214 info.append(message,0,msglen);
215 close(sock_id);
216 properties =Split(info,splitline,true);
217 vector<string>::iterator it;
218 for (it=properties.begin(); it<properties.end(); it++)
219 {
220 property= Split(*it,splittagbalue,true);
221 SplitProperty(property,&PName,&PValue);
222 if(PName=="Content-Length")
223 {
224 size =atoi(PValue.c_str());
225 break;
226 }
227 }
228 if(size==-1)
229 {
230 error->append("Resource Not Found!");
231 }
232
233 if (message!=NULL)
234 {
235 delete[] message;
236 message = NULL;
237 }
238 return size;
239
240 }
241
242
243 //给出的这样一个完整的url :"http://10.10.41.112/ressdir/test/111111111.lst"
244 //对应下面几个参数为:(注意格式)
245 //str1 = "10.10.41.112";
246 //str2 = "//ressdir//test//111111111.lst";
247 //str3 = "/mnt/sdcard/test/111111111.lst";
248
249 void CHttpDownLoad::DownLoad(string str1,string str2,string str3,void *handler)
250 {
251 if (str1.empty()||str2.empty()||str3.empty()||handler == NULL)
252 {
253 LOGI("0___DownLoad is error!!!");
254 return;
255 }
256
257 m_strIP = str1;
258 m_strFileName= str2;
259 m_strLocFile = str3;
260 m_pUdateBase = handler;
261
262 string error;
263 m_filesize = GetFileSize(str1.c_str(),str2.c_str(),&error,m_hsize);
264 if (m_filesize<=0)
265 {
266 LOGI("1_____DownLoad is error!!!");
267 return;
268 }
269
270 pthread_t thread_id;
271 pthread_attr_t attr;
272 pthread_attr_init(&attr);
273 pthread_attr_setdetachstate(&attr,PTHREAD_CREATE_DETACHED);
274 pthread_create(&thread_id,&attr,UpdateWorCoping,this);
275
276 m_thread_id = thread_id;
277 pthread_attr_destroy(&attr);
278 }
279
280 int CHttpDownLoad::GetDownState()
281 {
282 return m_iProgress;//用于下载进度
283 }
其中 updateBase 就是那个下载管理类,这里就不在贴出了。
在管理类中调用 DownLoad(string str1,string str2,string str3,void *handler);//此处主要格式,handler参数为下载管理类指针用于下载结束的回调
理进行http下载。
在下载过程中调用 GetDownStae() 获取下载的进度以用于其它目的。

浙公网安备 33010602011771号