首页 / 软件开发 / C++ / 使用CInternetSession封装多线程http文件下载
使用CInternetSession封装多线程http文件下载2010-11-02 crazy-bit 付黎如何下载一个http文件?我们当然可以用socket自己实现http协议去做,但费时费力还易出bug,对于一个客户端程序稳定易维护是第一位的,所幸MS给我们提供了功能强大的internet API函数族,MFC的CInternetSession对它们进行了一些简单的封装,但如此简单的封装对我等拿来主义者来说只是个半成品。必须经过再加工才能食用。先来介绍一下CInternetSession的使用:下面的代码是读取链接的基本方法:// CInternetSession在遇到一些错误时会抛出异常,因此必须包起来
TRY
{
CInternetSession sess ;
// 统一以二进制方式下载
DWORD dwFlag = INTERNET_FLAG_TRANSFER_BINARY|INTERNET_FLAG_DONT_CACHE|INTERNET_FLAG_RELOAD ;
CHttpFile * pF = (CHttpFile*)sess.OpenURL(strFilename, 1, dwFlag); ASSERT(pF);
if (!pF)
{AfxThrowInternetException(1);}
// 得到文件大小
CString str ;
pF->QueryInfo (HTTP_QUERY_CONTENT_LENGTH, str) ;
int nFileSize = _ttoi(str) ;
char * p = new[nFileSize] ;
while (true)
{
// 每次下载8Kb
int n = pF->Read (p, (nFileSize < 8192) ? nFileSize : 8192) ;
if (n <= 0)
break ;
p += n ; nFileSize -= n ;
}
delete[] p ;
delete pF ;
}
CATCH_ALL(e) {}
END_CATCH_ALL
这段代码有一个问题,在获取文件大小这个地方,对于静态网页 HTTP_QUERY_CONTENT_LENGTH 查询会返回文件大小,但对于asp,php这样的动态网页,查询会返回0。必须通过不断的调用 CHttpFile::GetLength 来一点一点累加内容,就像这样:int n = pF->GetLength() ;
while (n)
{
int * p = new BYTE[n] ;
pF->Read (p, n) ;
delete[] p ;
n = pF->GetLength() ;
}