ダウンローダー(DLoader)


■ 概略説明
ネット上のファイルをダウンロードするプログラムです。ネット上の指定したファイルを、PC上の指定したディレクトリにダウンロードし保存します。このサンプルは単一ファイルのみを扱います。

■ プログラムの説明
ダウンロードは下記の関数Download()をスレッドとして呼び出し、行います。
スレッドとして呼び出すことにより、ダウンロード中のメイン側のイベント処理を並列して行うことが可能です。
また、メイン側へのダウンロードの進み具合は、ユーザー定義のウィンドウメッセージにより行っています。
エラー処理は、try,catchによりなされています。エラーコードは調べていないので番号をそのまま表示しています。
従って、アドレスが違っていたのかタイムアウトなのか等の違いはこのプログラムでは判別していません。

UINT Download( LPVOID pParam)
{
CData* pdata = (CData*)pParam;

char buf[READ_BYTE_SIZE];
CInternetSession is;
CStdioFile *psf;
CString szFile;
DWORD time1, time2;
int readbyte;

szFile = pdata->m_sFile;
try
{
psf = is.OpenURL( szFile, 1, INTERNET_FLAG_TRANSFER_BINARY | INTERNET_FLAG_RELOAD);

pdata->m_nSize = psf->SeekToEnd(); // ファイルサイズの取得.
psf->SeekToBegin(); // ポインタを先頭に戻す.

pdata->m_pWnd->SendMessage( WM_DL_START);

CFile file( pdata->m_sPath,
CFile::modeCreate | CFile::modeWrite | CFile::typeBinary);

while ( 1)
{
if ( pdata->m_bStop) // 中断.
{
break;
}
time1 = ::GetTickCount();
readbyte = psf->Read( buf, READ_BYTE_SIZE); // 読込み.
if ( !readbyte)
break;
time2 = ::GetTickCount();

file.Write( buf, readbyte); // 書込み.
pdata->m_nDone += readbyte;
pdata->m_dwSpan += ( time2 - time1);
pdata->m_pWnd->SendMessage( WM_DL_PROG);
}
psf->Close();
file.Close();
delete psf;
}
catch( CInternetException *IE) // エラー処理.
{
pdata->m_dwError = IE->m_dwError;
pdata->m_bError = TRUE;
IE->Delete();
}

pdata->m_pWnd->SendMessage( WM_DL_END);

return 1;
}

メイン側からスレッドへのパラメータの受け渡しは、CDataというクラスのポインターにより行われます。
詳細は、CDataのソースコードを見てください。
現在試してはいませんが、複数のスレッドを同時に起動すると並列して複数のダウンロードを行えると思います。
またOpenURL関数のINTERNET_FLAG_RELOADは、毎回バッファを使わずにリロードします。
INTERNET_FLAG_BINARYは、バイナリーモードでデータを読み込み、改行コードの変更等は行いません。
psf = is.OpenURL( szFile, 1, INTERNET_FLAG_TRANSFER_BINARY | INTERNET_FLAG_RELOAD);
また、一回の読込みバイト数は1024になっていますが、幾つが最適な値かはわかりません。
ダウンロードの残り時間等の進捗の計算はいいかげんなのであまり信用しないで下さい。(笑)
このプログラムは基本部分のみのサンプルなので用途に応じて拡張してください。
■ ファイルのダウンロード
(MFC6.0プロジェクトファィル15KB)