インタネットからのファイルの取得(BASIC認証サポート)(32/64bit)

icon 項目のみ表示/展開表示の切り替え

概要

インターネットから指定された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);
}

実行ファイルとソースファイルのダウンロード