利用CAsyncMonikerFile下载文件

时间:2022-12-25 09:55:50
MFC类CAsyncMonikerFile可以用来从Internet上下载文件,其原理在于利用了COM对象Moniker.先上个例子:
class  CAsyncURLDownload :  public  CAsyncMonikerFile
{
public :
    CAsyncURLDownload();
    
virtual   ~ CAsyncURLDownload();

protected :
    
/*
    * 在异步约束操作中,调用OnDataAvailable来向客户提供有效的数据
    * dwSize:约束开始后数据传输的累计数(字节)。
    * dwBscfFlag:
                    BSCF_FIRSTDATANOTIFICATION 表示对一个特定的约束操作,第一次调用OnDataAvailable。  
                    BSCF_INTERMEDIATEDATANOTIFICATION 表示对一个特定的约束操作,中间调用OnDataAvailable。  
                    BSCF_LASTDATANOTIFICATION 表示对一个特定的约束操作,最后一次调用OnDataAvailable。  
    
*/
    
virtual   void  OnDataAvailable(DWORD dwSize, DWORD dwBscfFlag);

    
/*
    * 在数据下载过程中调用它来标示进度
    * ulProgress: 表示约束操作的当前进度号
    * ulProgressMax:表示调用OnProgress的操作中,ulProgress最大可能值。
    * ulStatusCode: 提供识别约束操作进度的附加信息。
    * szStatusText: 有关当前进度的信息,依赖于ulStatusCode的值。
    
*/
    
virtual   void  OnProgress(ULONG ulProgress, ULONG ulProgressMax, ULONG ulStatusCode, LPCTSTR szStatusText);
};
///////////////////// cpp文件 /////////////////////////////////////////////////////////////////////////////////////////////
CAsyncURLDownload::CAsyncURLDownload()
{
}

CAsyncURLDownload::
~ CAsyncURLDownload()
{
}

void  CAsyncURLDownload::OnDataAvailable( DWORD dwSize, DWORD dwBscfFlag )
{
    CAsyncMonikerFile::OnDataAvailable(dwSize, dwBscfFlag);

    
char  szBuffer[ 1024 ];
    UINT uBytesRead  
=    0 ;
    
    
// 打开文件
    HANDLE  hFile  =   ::CreateFile( _T( " D:\\config.ini " ),    GENERIC_READ | GENERIC_WRITE,    FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
        NULL, CREATE_ALWAYS, FILE_FLAG_BACKUP_SEMANTICS,    NULL    );
    
if ( INVALID_HANDLE_VALUE  ==  hFile ) 
        
return ;

    
do  
    {
        
// 读取已下载的数据
        uBytesRead  =   this -> Read( szBuffer, _countof( szBuffer )  -   1  );
        szBuffer[uBytesRead] 
=   ' \0 ' ;

        
// 写文件
        DWORD dwSizeToWrite  =   0 ;
        ::WriteFile( hFile, szBuffer, uBytesRead, 
& dwSizeToWrite, NULL );
    } 
while ( uBytesRead  ==  _countof( szBuffer )  -   1  );
    
    ::CloseHandle( hFile );
    
}

void  CAsyncURLDownload::OnProgress( ULONG ulProgress, ULONG ulProgressMax, ULONG ulStatusCode, LPCTSTR szStatusText )
{
    CAsyncMonikerFile::OnProgress(ulProgress, ulProgressMax, ulStatusCode, szStatusText);

    
if ( ulProgressMax  ==   0  )
        
return ;

    
// 在输出窗口输出进度值
    CString strHint;
    strHint.Format( _T(
" Progress: %d " ), ( int )(( float )ulProgress  /  ulProgressMax  *   100 ) );
    strHint 
+=  _T( " %\n " );
    ::OutputDebugString( strHint );
}
///////////////////////////////////////////////////////////////////////////////////////////// /
使用:CAsyncURLDownload  asyncDown;
    asyncDown.Open( _T(
" 下载地址 " ) );
PS: 这种下载方法缺乏健全的操作,比如中断下载等,这种下载方法只适合下载一些配置性的小文件,但是多一种手段多一份选择,这种方案毕竟比开线程下载简单的多,而且贵在这种下载不会阻塞线程.