山本ワールド
Windowsプログラミング
アルゴリズム Vitual C++ 2008/2013によるWin32/Win64 APIレベルのプログラム 基礎 Vitual C++ 2008/2013によるAPIレベルのプログラム(32/64bit) Wix3でインストーラーを作る Visual C++ 2008 Standard Editonによるフォームアプリケーションのプログラム(32/64bit) Vitual C++ 2008 Standard EditonによるAPIレベルのプログラム(32/64bit) Windows 7対応 Visual C++ 2008 ExpressによるAPIレベルのプログラム Visual C++ 2005 ExpressによるAPIレベルのプログラム Visual C++ Versiosn 5 BORLAND C++ Windowsプログラム全般 Excel VBA その他インタネットからのファイルの取得(BASIC認証サポート)(32/64bit)
概要
インターネットから指定されたURLのファイルをダウンロードし保存します。BASIC認証に対応しています。ユーザー名およびパスワードはプログラムのソースコードで指定しています。
テスト環境
コンパイラ
Visual C++ 2008/2013 Express 32/64bit マルチバイト/UNICODE実行環境
Windows XP Professional Service Pack 3 32bit(Virtual Box上の仮想マシーン)Windows 7 Enterprise Service Pack 1 64bit
プログラムソースの概要
webget.cpp
_tmain
バイナリモードでファイルをオープン及びダウンロードする関数HtmlGet2を呼び出します。保存ファイル名は、_tfopen関数の引数で設定します。ここではtest.htmlとしている。
URLはHtmlGet2関数の第1引数で指定します。
HtmlGet2
InternetCrackUrl APIによりURLからサーバー名等を取得します。インターネットのサービスをInternetOpen APIによりオープンします。
InetrnetConnect APIによりサーバーに接続します。
HttpOpenRequest APIによりサーバーリクエストを初期化し、HttpSendRequest APIによりリクエストします。
HttpQueryInfo APIによりリクエストに対するステータス(答え)を取得します。 この時、エラーステータスが返された場合、終了します。ここでいうエラーとはお馴染みの403等です。
401エラーが返された場合、InternetSetOption APIによりユーザー名とパスワードを設定し、HttpSendRequest APIからやり直します。
ステータスが正常になった場合、InternetReadFile APIによりファイルを読み込みfwrite関数でファイルに書き込みます。
読み込みが終了したら、各ハンドルをInternetCloseHandle APIにより閉じます。
ソースコード
webget.cpp
// インターネットからファイルをダウンロードする(認証付)
#include <windows.h>
#include <wininet.h>
#include <stdio.h>
#include <tchar.h>
#include <locale.h>
#pragma comment(lib,"wininet.lib")
bool HtmlGet2(TCHAR* url,FILE* fp){
URL_COMPONENTS uc;
HINTERNET hiopen;
HINTERNET hiconnect;
HINTERNET hirequest;
TCHAR host_name[64];
TCHAR path[64];
TCHAR buf[64];
char read_buf[4096];
ZeroMemory(&uc , sizeof(URL_COMPONENTS));
uc.dwStructSize=sizeof(URL_COMPONENTS);
uc.lpszHostName=host_name;
uc.lpszUrlPath=path;
uc.dwHostNameLength=sizeof(host_name)/sizeof(TCHAR);
uc.dwUrlPathLength=sizeof(path)/sizeof(TCHAR);
// URLの解析
unsigned url_len=(unsigned)_tcslen(url);
if( InternetCrackUrl(url , url_len , ICU_ESCAPE , &uc )==FALSE){
MessageBox(0,_TEXT("InternetCrackUrl:URLの解析に失敗しました。"),_TEXT("エラー"),MB_OK);
return false;
}
MessageBox(0,uc.lpszHostName,_TEXT("サーバー名"),MB_OK);
MessageBox(0,uc.lpszUrlPath,_TEXT("パス"),MB_OK);
_stprintf_s(buf,sizeof(buf)/sizeof(TCHAR),_TEXT("ポート:%i"),uc.nPort);
MessageBox(0,buf,_TEXT("ポート"),MB_OK);
DWORD flags=0;
if(uc.nScheme==INTERNET_SCHEME_HTTP){
flags= INTERNET_FLAG_RELOAD | INTERNET_FLAG_DONT_CACHE | INTERNET_FLAG_NO_AUTO_REDIRECT;
}else if(uc.nScheme==INTERNET_SCHEME_HTTPS){
flags=INTERNET_FLAG_RELOAD | INTERNET_FLAG_DONT_CACHE | INTERNET_FLAG_NO_AUTO_REDIRECT
| INTERNET_FLAG_SECURE | INTERNET_FLAG_IGNORE_CERT_DATE_INVALID
| INTERNET_FLAG_IGNORE_CERT_CN_INVALID;
}else{
MessageBox(0,_TEXT("HTTPでもHTTPSでもありません"),_TEXT("エラー"),MB_OK);
return false;
}
_stprintf_s(buf,sizeof(buf)/sizeof(TCHAR),_TEXT("%s"),uc.lpszUrlPath);
// インターネットのサービスハンドルの取得(レジストリ内のIEの設定を使用)
hiopen=InternetOpen(_TEXT("inetdemo"),INTERNET_OPEN_TYPE_PRECONFIG, NULL, NULL, 0 );
if(hiopen==NULL){
MessageBox(0,_TEXT("InternetOpenで初期化に失敗しました"),_TEXT("エラー"),MB_OK);
return false;
}
// HTTPサーバーへの接続
hiconnect=InternetConnect(hiopen , uc.lpszHostName , uc.nPort , NULL , NULL , INTERNET_SERVICE_HTTP , 0 , 0);
if(hiconnect==NULL){
InternetCloseHandle(hiopen);
MessageBox(0,_TEXT("InternetConnectでHTTP接続に失敗しました"),_TEXT("エラー"),MB_OK);
return false;
}
// HTTPサーバーへのリクエストの初期化
hirequest=HttpOpenRequest(hiconnect,_TEXT("GET"),buf,NULL,NULL,NULL,flags,NULL);
if(hirequest==NULL){
InternetCloseHandle(hiconnect);
InternetCloseHandle(hiopen);
MessageBox(0,_TEXT("HttpOpenRequestでHTTP接続に失敗しました"),_TEXT("エラー"),MB_OK);
return false;
}
flags=0;
do{
if(HttpSendRequest(hirequest , NULL , 0 , NULL , 0)==FALSE){
InternetCloseHandle(hirequest);
InternetCloseHandle(hiconnect);
InternetCloseHandle(hiopen);
MessageBox(0,_TEXT("HtpSendRequestでHTTP要求送信に失敗しました"),_TEXT("エラー"),MB_OK);
return false;
}
// HTTPリクエストに関連する情報を取得する(ステータスコードを32ビットで返す)
DWORD status_code=0;
DWORD len=sizeof(DWORD);
if(HttpQueryInfo( hirequest , HTTP_QUERY_STATUS_CODE | HTTP_QUERY_FLAG_NUMBER,&status_code,&len,0)==FALSE){
InternetCloseHandle(hirequest);
InternetCloseHandle(hiconnect);
InternetCloseHandle(hiopen);
MessageBox(0,_TEXT("HttpQueryInfo HTTP要求に対応するステータスコードの取得に失敗"),_TEXT("エラー"),MB_OK);
return false;
}
if( status_code != HTTP_STATUS_OK){
if(status_code==HTTP_STATUS_DENIED || status_code==HTTP_STATUS_PROXY_AUTH_REQ){
// ユーザー名とパスワードを設定
TCHAR* username=_TEXT(""); // ユーザー名の設定
TCHAR* password=_TEXT(""); // パスワードの設定
InternetSetOption(hirequest,INTERNET_OPTION_USERNAME , username, (DWORD)_tcslen(username));
InternetSetOption(hirequest, INTERNET_OPTION_PASSWORD , password, (DWORD)_tcslen(password));
++flags;
}else{
InternetCloseHandle(hirequest);
InternetCloseHandle(hiconnect);
InternetCloseHandle(hiopen);
TCHAR msg[64];
flags=0;
_stprintf_s(msg,sizeof(msg)/sizeof(TCHAR),_TEXT("HttpQueryInfo ステータスコード%iはエラーです"),status_code);
MessageBox(0,msg,_TEXT("エラー"),MB_OK);
return false;
}
}else
flags=0;
}while(flags==1);
DWORD read_size;
do{
if( InternetReadFile( hirequest , read_buf , sizeof(read_buf) , &read_size )==0){
MessageBox(0,_TEXT("HttpQueryInfo ステータスコードはエラーです"),_TEXT("エラー"),MB_OK);
InternetCloseHandle(hirequest);
InternetCloseHandle(hiconnect);
InternetCloseHandle(hiopen);
return false;
}
fwrite(read_buf,sizeof(read_buf[0]),read_size,fp);
}while(0<read_size);
InternetCloseHandle(hirequest);
InternetCloseHandle(hiconnect);
InternetCloseHandle(hiopen);
return true;
}
void _tmain(int argc,TCHAR** argv){
_tsetlocale(LC_ALL,_TEXT(""));
FILE* fp;
_tfopen_s(&fp,_TEXT("test.html"),_TEXT("wb"));
// URL , ファイルポインタ
HtmlGet2(_TEXT("http://yamatyuu.net/index.html"),fp);
fclose(fp);
}
Copyright (C) 2012 山本ワールド All Rights Reserved.