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
");    
 87     request.append("Host:");   
 88     request.append(host);   
 89     request.append("

");      
 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="
";    
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
");    
187     request.append("Host:");    
188     request.append(host);    
189     request.append("

");
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() 获取下载的进度以用于其它目的。

原文地址:https://www.cnblogs.com/wainiwann/p/3214835.html