// インターネットファイルのダウンロード // (C)2003 Yutaka Wada, AirparkLab // [注意] // 相対パスで読み込めるように便宜上ヘッダファイルにしている。 // インクルードするのは唯一のソースファイルのみとし、他はextern宣言して使用すること。 /* 使用例 #include "InetDownload.h" // ダウンロードファイルの決定 char szUrl = "http://www.hoge.com/image.jpg"; char szPath[MAX_PATH], szElementName[MAX_PATH], szFilename[MAX_PATH]; GetTempPath( MAX_PATH, szPath ); // テンポラリディレクトリの取得 (文字列末に\がつくことに注意) sprintf( szFilename, "%s%s", szPath, InetElementNameGet( szUrl, szElementName ) ); int nSize = InetDownloadFile( szUrl, szFilename, 0 ); ダウンロードしたいファイルの URL と、ダウンロードファイル名を指定します。 ダウンロードファイルと同名既存ファイルは上書きされるので注意してください。 戻り値はファイルサイズで、-1 であればダウンロード失敗です。 ※注意 wininet.dll を使用しているため InternetExplorer 4.0 以降がインストールされていないと使用できません。 サブスレッドで実行するとファイル作成をしても消えてしまう?ことがあります。InetDownloadBuffer()を使ってみてください。 */ #ifndef __INET_DOWNLOAD_H__ #define __INET_DOWNLOAD_H__ #include #include #include #include #include // プロトタイプ宣言 int InetDownloadFile( const char *pURL, const char *pFilename, unsigned long dwFlag ); int InetDownloadBuffer( const char *pURL, unsigned char **pBuffer, unsigned long dwFlag ); char* InetElementNameGet( const char *pUrl, char *pElementName ); // DLL関数の定義 typedef HANDLE HINTERNET; typedef HINTERNET (WINAPI *INTERNET_OPEN)( LPCTSTR, DWORD, LPCTSTR, LPCSTR, DWORD ); typedef HINTERNET (WINAPI *INTERNET_OPEN_URL)( HINTERNET, LPCTSTR, LPCTSTR, DWORD, DWORD, DWORD ); typedef BOOL (WINAPI *INTERNET_READ_FILE)( HINTERNET, LPVOID, DWORD, LPDWORD ); typedef BOOL (WINAPI *INTERNET_CLOSE_HANDLE)( HINTERNET ); #define INTERNET_OPEN_TYPE_PRECONFIG 0x00000000 #define INTERNET_FLAG_OFFLINE 0x01000000 // エージェント定義 #define AGENT "Mozilla/4.0 (compatible; MSIE 5.0; Windows 95)" // ダウンロードブロックサイズ #define READ_BLOCK_SIZE (256*1024) // インターネットファイルを指定したファイルにダウンロードする // 引数 URL文字列とファイル名文字列へのアドレス // 戻値 サイズ int InetDownloadFile( const char *pURL, const char *pFilename, unsigned long dwFlag ) { unsigned char *pBuffer; int nSize = InetDownloadBuffer( pURL, &pBuffer, dwFlag ); // ダウンロード成功の場合 if( nSize > 0 ){ // バッファの内容をファイルに書き出す CFile DownloadFile; if( DownloadFile.Open( pFilename, CFile::modeCreate|CFile::modeWrite ) ){ DownloadFile.Write( pBuffer, nSize ); DownloadFile.Flush(); DownloadFile.Close(); } else nSize = 0; } else nSize = 0; /* バッファ解放 */ if( pBuffer ) free( pBuffer ); // ファイルサイズを返し終了 return( nSize ); } // インターネットファイルイメージをダウンロードして確保したバッファに書き込む // 引数 URL文字列とバッファポインタへのアドレス // 戻値 サイズ // バッファは確保せずにポインタだけ渡してください( InetDownloadFile()参照 )。 // 関数使用後,バッファポインタがNULLでない場合は free() を行ってバッファを開放してください。 int InetDownloadBuffer( const char *pURL, unsigned char **pBuffer, unsigned long dwFlag ) { // バッファポインタの初期化 *pBuffer = NULL; // DLLのロード HMODULE hLib = LoadLibrary( "wininet.dll" ); if( hLib == NULL ) return( -1 ); // DLL関数の取得 INTERNET_OPEN InternetOpen = (INTERNET_OPEN)GetProcAddress( hLib, "InternetOpenA" ); INTERNET_OPEN_URL InternetOpenUrl = (INTERNET_OPEN_URL)GetProcAddress( hLib, "InternetOpenUrlA" ); INTERNET_READ_FILE InternetReadFile = (INTERNET_READ_FILE)GetProcAddress( hLib, "InternetReadFile" ); INTERNET_CLOSE_HANDLE InternetCloseHandle = (INTERNET_CLOSE_HANDLE)GetProcAddress( hLib, "InternetCloseHandle" ); if( InternetOpen == NULL || InternetOpenUrl == NULL || InternetReadFile == NULL || InternetCloseHandle == NULL ){ FreeLibrary( hLib ); return( -1 ); } // DLL初期化 HINTERNET hInet = InternetOpen( AGENT, INTERNET_OPEN_TYPE_PRECONFIG, NULL, NULL, dwFlag ); // URLを開く HINTERNET hFile; char szHeader[MAX_PATH]; sprintf( szHeader, "Referer:%s\r\n\r\n", pURL ); if( hInet ) hFile = InternetOpenUrl( hInet, pURL, szHeader, strlen( szHeader ), 0, 0 ); // URLからデータを読み込む BYTE *pb = NULL; BYTE *pBuff = NULL; size_t BuffSize = 0; DWORD ReadSize = 0; DWORD FileSize = 0; int nBlock = 0; BOOL bRet; if( hFile ){ // サイズが分からないのでブロックサイズ毎にメモリを拡張して読み込む for( ; ; ){ // メモリの確保(拡張) pb = (BYTE *)realloc( pBuff, BuffSize + READ_BLOCK_SIZE ); if( pb ) pBuff = pb; else break; BuffSize = _msize( pBuff ); // ファイルの読み込み bRet = InternetReadFile( hFile, pBuff+nBlock*READ_BLOCK_SIZE, READ_BLOCK_SIZE, &ReadSize ); // ファイルサイズとブロック数の更新 FileSize += ReadSize; nBlock++; // 読み込み終了の場合 if( bRet == FALSE || ReadSize < READ_BLOCK_SIZE ) break; } } // URLを閉じる if( hFile ) InternetCloseHandle( hFile ); if( hInet ) InternetCloseHandle( hInet ); // DLL解放 FreeLibrary( hLib ); // ダウンロード成功の場合 if( pBuff && bRet == TRUE && FileSize > 0 ){ // サイズ分のメモリを確保しなおす(メモリ確保しすぎの是正) pb = (BYTE *)realloc( pBuff, FileSize ); if( pb ) pBuff = pb; *pBuffer = pBuff; } // 失敗の場合 else{ if( pBuff ) free( pBuff ); *pBuffer = NULL; FileSize = 0; } // ファイルサイズを返し終了 return( FileSize ); } // URL からエレメント名(ファイル名)を戻す // pUrl で与えられた URL 文字列からエレメント名を抽出し,pElementName に書き込む。 // 戻り値のアドレスは引数である pElementName のアドレスである。 // ファイル名として使用できない文字は "_" に変更されることに注意すること。 char* InetElementNameGet( const char *pUrl, char *pElementName ) { int nLen, i, j; // セパレータ文字'/'の検索 nLen = strlen( pUrl ); for( i=nLen-1; i>=0; i-- ){ if( pUrl[i] == '/' ){ i++; break; } } // 抽出失敗の場合テンポラリファイル名を戻す if( i >= nLen || i < 0 || pUrl[i] == '\0' ) strcpy( pElementName, "unknown.dat" ); // 抽出成功の場合 else { // ファイル名として使用できない文字を変換する。 char c; for( j=0; pUrl[i] != '\0'; j++ ){ c = pUrl[i]; if( c == '\\' || c == '/' || c == ':' || c == '*' || c == '?' || c == '"' || c == '<' || c == '>' || c == '|' ) c = '_'; pElementName[j] = c; i++; } pElementName[j] = '\0'; // 拡張子以後の文字列は省略する nLen = strlen( pElementName ); for( i=0; i