Http文件下载类源代码

类别:编程语言 点击:0 评论:0 推荐:

// HttpClient.h: HTTP协议客户端的实现类
//
//////////////////////////////////////////////////////////////////////

#if !defined(_HTTPCLIENT_H__)
#define _HTTPCLIENT_H__

#include "../comm/tcp.h"

#pragma warning(disable : 4786)

#include <map>
#include <string>
using namespace std;

#define  BUFFER_SIZE 8192
#define  HEADS_BUFFER_SIZE 2048
#define  PEEK_SIZE 500
#define  TCP_TIMEOUT 5

class CHttpClient
{
public:
 void Cancel();
 const char* GetStatusString();
 CHttpClient();
 virtual ~CHttpClient();

 bool Download(char* url,char* fname);                  //直接下载到文件
 bool Download(char* url,HWND hParent,long msg = WM_USER+1);  //消息方式下载数据流

 inline long Instr(char* from,char* find);
 virtual void OnDataRecived(char* data,long datasize,int first = false );
 long GetHostName(char *url, char *buf);
 int GetStatus();
 long GetHeader(char* headname,char* buf);
 long GetHeader(char* from,char* searchfor,char* buf);
 bool Reset();
private:
 long m_Message;
 HWND m_hParent;
 bool m_noCancel;
 char m_fname[BUFFER_SIZE];
 int m_status;
 char m_heads_buffer[HEADS_BUFFER_SIZE];
 char m_buffer[BUFFER_SIZE+1];
 CTcp tcp;

 map<const int,string> m_map;
};

#endif


//----------------------------------------------------------------
// HttpClient.cpp: implementation of the CHttpClient class.
//
//////////////////////////////////////////////////////////////////////

#include "stdafx.h"
#include "HttpClient.h"

#ifdef _DEBUG
#undef THIS_FILE
static char THIS_FILE[]=__FILE__;
#define new DEBUG_NEW
#endif

//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////

CHttpClient::CHttpClient()
{
 Reset();
 memset(m_fname,0,BUFFER_SIZE);
 tcp.init();
 
 m_map[100]= "Continue";
 m_map[101]= "Switching Protocols";
 m_map[200]= "OK";
 m_map[201]= "Created";
 m_map[202]= "Accepted";
 m_map[203]= "Non-Authoritative Information";
 m_map[204]= "No Content";
 m_map[205]= "Reset Content";
 m_map[206]= "Partial Content";
 m_map[300]= "Multiple Choices";
 m_map[301]= "Moved Permanently";
 m_map[302]= "Found";
 m_map[303]= "See Other";
 m_map[304]= "Not Modified";
 m_map[305]= "Use Proxy";
 m_map[307]= "Temporary Redirect";
 m_map[400]= "Bad Request";
 m_map[401]= "Unauthorized";
 m_map[402]= "Payment Required";
 m_map[403]= "Forbidden";
 m_map[404]= "Not Found";
 m_map[405]= "Method Not Allowed";
 m_map[406]= "Not Acceptable";
 m_map[407]= "Proxy Authentication Required";
 m_map[408]= "Request Time-out";
 m_map[409]= "Conflict";
 m_map[410]= "Gone ";
 m_map[411]= "Length Required";
 m_map[412]= "Precondition Failed";
 m_map[413]= "Request Entity Too Large";
 m_map[414]= "Request-URI Too Large";
 m_map[415]= "Unsupported Media Type";
 m_map[416]= "Requested range not satisfiabl";
 m_map[417]= "Expectation Failed";
 m_map[500]= "Internal Server Error";
 m_map[501]= "Not Implemented";
 m_map[502]= "Bad Gateway";
 m_map[503]= "Service Unavailable";
 m_map[504]= "Gateway Time-out";
 m_map[505]= "HTTP Version not supported";
}

CHttpClient::~CHttpClient()
{

}

bool CHttpClient::Reset()
{
 m_noCancel=true;
 m_hParent=NULL;
 m_Message=0;
 memset(m_buffer,0,BUFFER_SIZE);
 memset(m_heads_buffer,0,HEADS_BUFFER_SIZE);
 return 1;
}

//HTTP下载主程序
bool CHttpClient::Download(char *url, HWND hParent,long msg)
{
 m_Message=m_Message;
 m_hParent=hParent;

 //状态为忙

 Reset();
 char hostname[256];
 memset(hostname,0,256);
 GetHostName(url,hostname);

 long AllSize=0;
 long ReadSize=0;
 bool headFinished=false;

 int s;
 s=tcp.connect(hostname,80,TCP_TIMEOUT,1);
 if(s<0)
  return false;

 sprintf(m_buffer,"GET %s HTTP/1.0 \r\nHost:%s\r\nAccept:*/*\r\nUser-Agent: AutoUpdate/1.0 \r\n\r\n",url,hostname);
 tcp.send(s,m_buffer,strlen(m_buffer),TCP_TIMEOUT);

 //先取PEEK_SIZE个字节,这样可以确保取到Content-Length
 ReadSize=tcp.recv(s,m_buffer,PEEK_SIZE,TCP_TIMEOUT);
 if(ReadSize==-1)
  return false;
 m_buffer[ReadSize]=0;

 memset(hostname,0,256);

 int m,n;
 m=Instr(m_buffer," ");
 n=Instr(m_buffer+m+1," ");
 memcpy(hostname,m_buffer+m+1,n);

 m_status=atoi(hostname);
 if(m_status!=200)return false;

 memset(hostname,0,256);
 if(GetHeader(m_buffer,"Content-Length",hostname)<0)
  return false;

 //取得内容总长度
 AllSize=atol(hostname);
 memset(hostname,0,256);

 //寻找HTTP数据区表示
 int i;
 i=Instr(m_buffer,"\r\n\r\n");
 if(i>0)
 {
  memcpy(m_heads_buffer,m_buffer,i+4);
  headFinished=true;
  ReadSize=ReadSize-i-4;
  OnDataRecived(m_buffer+i+4,ReadSize,true);
 }

 while(ReadSize<AllSize && m_noCancel)
 {
  int nSize;
  if(headFinished)
  {
   nSize=(AllSize-ReadSize)>BUFFER_SIZE?BUFFER_SIZE:(AllSize-ReadSize);
   memset(m_buffer,0,BUFFER_SIZE);
   if(tcp.recv(s,m_buffer,nSize,TCP_TIMEOUT)!=nSize)
    return false;
   ReadSize+=nSize;
   m_buffer[nSize]=0;

   OnDataRecived(m_buffer,nSize);
  }
  else
  {
   nSize=(AllSize-ReadSize)>(BUFFER_SIZE-ReadSize)?(BUFFER_SIZE-ReadSize):(AllSize-ReadSize);
   if(tcp.recv(s,m_buffer+ReadSize,nSize,TCP_TIMEOUT)!=nSize)
    return false;
   ReadSize+=nSize;
   m_buffer[nSize]=0;
   //寻找HTTP数据区表示
   i=Instr(m_buffer,"\r\n\r\n");
   if(i>0)
   {
    memcpy(m_heads_buffer,m_buffer,i+4);
    headFinished=true;
    ReadSize=ReadSize-i-4;
    OnDataRecived(m_buffer+i+4,ReadSize,true);
   }
  }
 }
 
 if(!m_noCancel)remove(m_fname);

 tcp.close(s);
 return true;
}


int CHttpClient::GetStatus()
{
 return m_status;
}

//从URL中取出主机名
long CHttpClient::GetHostName(char *url, char *buf)
{
 int i,j;
 char* lpsz = _tcsstr(url, "//");
 if(!lpsz)return -1;
 i=lpsz-url+2;

 lpsz= _tcsstr(url+i, "/");
 if(!lpsz)return -1;
 j=lpsz-url;
 
 memcpy(buf,url+i,j-i);
 return j-i;
}

long CHttpClient::GetHeader(char *headname, char *buf)
{
 return GetHeader(m_heads_buffer,headname,buf);
}

long CHttpClient::GetHeader(char *from, char *headname, char *buf)
{
 char *p;
 char* lpsz = _tcsstr(from, headname);
 if(!lpsz)return -1;

 //lpsz++;
 p=lpsz+strlen(headname)+2;
 lpsz = _tcsstr(p, "\r\n");

 if(!lpsz)return -1;

 memcpy(buf,p,lpsz-p);

 return strlen(buf);
}

void CHttpClient::OnDataRecived(char* data,long datasize ,int first)
{

 if(m_hParent)
  ::SendMessage(m_hParent,m_Message,(unsigned int)data,datasize);
 else
 {
  if(first)remove(m_fname);
  FILE* f=fopen(m_fname,"ab");
  if(f){
   fwrite(data,1,datasize,f);
   fclose(f);
  }
 }
 //处理数据,一定要拷贝走哦,缓冲区可是循环使用的
}

inline long CHttpClient::Instr(char *from, char *find)
{
 char* lpsz = _tcsstr(from, find);
 return (!lpsz)?-1:lpsz-from;
}

bool CHttpClient::Download(char *url, char *fname)
{
 strcpy(m_fname,fname);
 return Download(url,NULL,NULL);
}

const char* CHttpClient::GetStatusString()
{
 return m_map[m_status].c_str();
}

void CHttpClient::Cancel()
{
 m_noCancel=false;
}

本文地址:http://com.8s8s.com/it/it26474.htm