head文件 httpdown.h #pragma once #include <afxinet.h> #define HTTP_MAX_TASK_NUM 1024 #define SZ_HEAD "Accept: */*/r/nUser-Agent: Mozilla/4.0 (compatible; MSIE 5.00; Windows 98)/r/n" struct TASK { CString url; CString savepath; CString filename; DWORD filetotalsize; DWORD filecurrentdownsize; int speed; int taskid; int state;//0空闲 1下载中 2下载完成 3下载失败 int isruning;//0 停止 1运行中 CRITICAL_SECTION c_s; }; class HttpDownload { public: HttpDownload(void); ~HttpDownload(void); int InitMission(); int ClearMission(); int AddHttpMission(CString url,CString savepath,CString filename); int StopMission(int taskid); int GetMissionStatus(int taskid,int &state,int &speed,DWORD &filetotalsize,DWORD &filecurrentdownsize); public: TASK tasklist[HTTP_MAX_TASK_NUM]; CRITICAL_SECTION c_s; }; 具体实现 httpdown.cpp #include "StdAfx.h" #include "./httpdownload.h" #include <Mmsystem.h> void Download(CString url,CString savepath,CString filename,TASK *task); UINT DownloadThread(LPVOID lpPram) { TASK *task=(TASK*)(lpPram); Download(task->url,task->savepath,task->filename,task); return 1; } void Download(CString url,CString savepath,CString filename,TASK *task) { CFile file; CString filepath; if(savepath.Right(1)!="//") { filepath.Format("%s//%s",savepath,filename); }else { filepath.Format("%s%s",savepath,filename); } CFileException fileException; if(!file.Open(filepath,CFile::modeCreate|CFile::modeNoTruncate|CFile::modeReadWrite|CFile::shareDenyWrite|CFile::typeBinary,&fileException)) { printf("open file fail [%d]/n",fileException.m_cause); task->state=3; return; } CString strRangeQuest; if (file.GetLength()>0) { file.SeekToEnd(); strRangeQuest.Format( _T("%sRange: bytes=%d-/r/n"), SZ_HEAD,file.GetLength()); task->filecurrentdownsize=file.GetLength(); } else { strRangeQuest = SZ_HEAD; } CInternetSession session; CHttpConnection* pHttpConnection = NULL; CHttpFile* pHttpFile = NULL; CString strServer, strObject; INTERNET_PORT wPort; DWORD dwType; const int nTimeOut = 2000; session.SetOption(INTERNET_OPTION_CONNECT_TIMEOUT, nTimeOut); //重试之间的等待延时 session.SetOption(INTERNET_OPTION_CONNECT_RETRIES, 1); //重试次数 char* pszBuffer = NULL; try { AfxParseURL(url, dwType, strServer, strObject, wPort); pHttpConnection = session.GetHttpConnection(strServer, wPort); //pHttpFile = pHttpConnection->OpenRequest(CHttpConnection::HTTP_VERB_GET, strObject); pHttpFile=pHttpConnection->OpenRequest(CHttpConnection::HTTP_VERB_GET,strObject,NULL,1,NULL,NULL,INTERNET_FLAG_DONT_CACHE); pHttpFile->AddRequestHeaders(strRangeQuest); if(pHttpFile->SendRequest() == FALSE) return; DWORD dwStateCode; pHttpFile->QueryInfoStatusCode(dwStateCode); if(dwStateCode == HTTP_STATUS_OK || dwStateCode == HTTP_STATUS_PARTIAL_CONTENT) { char szInfoBuffer[1000]; //返回消息 DWORD dwInfoBufferSize = sizeof(szInfoBuffer); BOOL bResult = FALSE; bResult = pHttpFile->QueryInfo(HTTP_QUERY_CONTENT_LENGTH, (void*)szInfoBuffer,&dwInfoBufferSize,NULL); task->filetotalsize=atoi(szInfoBuffer)+task->filecurrentdownsize; DWORD starttime=timeGetTime(); const int BUFFER_LENGTH = 1024 * 10; pszBuffer = new char[BUFFER_LENGTH]; //读取文件的缓冲 UINT nRead = pHttpFile->Read(pszBuffer, BUFFER_LENGTH); //读取服务器上数据 UINT nReadCount=0; while(nRead>0) { file.Write(pszBuffer,nRead);//写到本地文件 EnterCriticalSection(&task->c_s); task->filecurrentdownsize+=nRead; DWORD elapsed=timeGetTime()-starttime; nReadCount+=nRead; if(elapsed>3000) { task->speed=(nReadCount/1024)/(elapsed/1000); starttime=timeGetTime(); nReadCount=0; } //printf("task speed=%d/n",task->speed); LeaveCriticalSection(&task->c_s); nRead = pHttpFile->Read(pszBuffer, BUFFER_LENGTH); if(task->isruning==0) { break; } } delete[]pszBuffer; pszBuffer = NULL; file.Close(); EnterCriticalSection(&task->c_s); task->state=2; LeaveCriticalSection(&task->c_s); } else { delete[]pszBuffer; pszBuffer = NULL; if(pHttpFile != NULL) { pHttpFile->Close(); delete pHttpFile; pHttpFile = NULL; } if(pHttpConnection != NULL) { pHttpConnection->Close(); delete pHttpConnection; pHttpConnection = NULL; } session.Close(); file.Close(); EnterCriticalSection(&task->c_s); task->state=3; LeaveCriticalSection(&task->c_s); return; } } catch(...) { delete[]pszBuffer; pszBuffer = NULL; if(pHttpFile != NULL) { pHttpFile->Close(); delete pHttpFile; pHttpFile = NULL; } if(pHttpConnection != NULL) { pHttpConnection->Close(); delete pHttpConnection; pHttpConnection = NULL; } session.Close(); file.Close(); EnterCriticalSection(&task->c_s); task->state=3; LeaveCriticalSection(&task->c_s); return; } if(pHttpFile != NULL) pHttpFile->Close(); if(pHttpConnection != NULL) pHttpConnection->Close(); session.Close(); } HttpDownload::HttpDownload(void) { InitializeCriticalSection(&c_s); InitMission(); } HttpDownload::~HttpDownload(void) { DeleteCriticalSection(&c_s); for(int i=0;i<HTTP_MAX_TASK_NUM;i++) { tasklist[i].state=0; tasklist[i].taskid=0; tasklist[i].filetotalsize=0; tasklist[i].filecurrentdownsize=0; tasklist[i].isruning=0; tasklist[i].speed=0; DeleteCriticalSection(&tasklist[i].c_s); } } int HttpDownload::InitMission() { for(int i=0;i<HTTP_MAX_TASK_NUM;i++) { tasklist[i].state=0; tasklist[i].taskid=i+1; tasklist[i].filetotalsize=0; tasklist[i].filecurrentdownsize=0; tasklist[i].isruning=0; tasklist[i].speed=0; InitializeCriticalSection(&tasklist[i].c_s); } return 1; } int HttpDownload::ClearMission() { for(int i=0;i<HTTP_MAX_TASK_NUM;i++) { tasklist[i].isruning=0; } return 1; } int HttpDownload::AddHttpMission(CString url,CString savepath,CString filename) { int taskid=-1; EnterCriticalSection(&c_s); for(int i=0;i<HTTP_MAX_TASK_NUM;i++) { if(tasklist[i].state==0) { tasklist[i].url=url; tasklist[i].savepath=savepath; tasklist[i].filename=filename; tasklist[i].state=1; tasklist[i].isruning=1; taskid=tasklist[i].taskid; AfxBeginThread(DownloadThread,&tasklist[i]); break; } } LeaveCriticalSection(&c_s); return taskid; } int HttpDownload::StopMission(int taskid) { int index=taskid-1; int ret=-1; if(index>=0) { EnterCriticalSection(&tasklist[index].c_s); if(tasklist[index].state!=0) { tasklist[index].isruning=0; ret=1; } LeaveCriticalSection(&tasklist[index].c_s); } return ret; } int HttpDownload::GetMissionStatus(int taskid,int &state,int &speed,DWORD &filetotalsize,DWORD &filecurrentdownsize) { int index=taskid-1; int ret=-1; if(index>=0) { EnterCriticalSection(&tasklist[index].c_s); if(tasklist[index].state!=0) { state=tasklist[index].state; speed=tasklist[index].speed; filetotalsize=tasklist[index].filetotalsize; filecurrentdownsize=tasklist[index].filecurrentdownsize; ret=1; } LeaveCriticalSection(&tasklist[index].c_s); } return ret; }