読者です 読者をやめる 読者になる 読者になる

WinINet(InternetReadFile)によるファイル(HTMLも含む)のダウンロード

vc
int Web_Downloader(char *Server_Host_Address, char *FileLocation, char *Referer , char *SaveDirectory , char *SaveName )
{
        //返り値一覧
        //
        //-106:ERR_INTERNET_DISCONNECTED        インターネットに接続されていない。
        //-403:"403 Forbidden"                                サーバーにリクエストが拒否された。
        //-404:"404 Not Found"                                指定したURLにドキュメントが存在しない。
        //-1                                                                その他のエラー

        HINTERNET hInternet;
        HINTERNET hHttpSession;
        HINTERNET hHttpRequest;
        
        // WININET初期化
        hInternet = InternetOpen(
                "Web_Downloader",
                INTERNET_OPEN_TYPE_PRECONFIG,
                NULL,
                NULL,
                0);

        // サーバへ接続
        hHttpSession = InternetConnect(
                hInternet,
                Server_Host_Address,
                INTERNET_DEFAULT_HTTP_PORT,//HTTP_PORT
                NULL,
                NULL,
                INTERNET_SERVICE_HTTP,//SERVICE_HTTP
                0,
                0);

        // HTTP要求の作成
        hHttpRequest = HttpOpenRequest(
                hHttpSession,
                "GET",
                FileLocation,
                NULL,
                Referer,
                NULL,
                0,
                0);

        // 作成したHTTP要求の発行
        BOOL bHttpSendRequest = HttpSendRequest(
                        hHttpRequest,
                        NULL,
                        0,
                        NULL,
                        0);
        if( bHttpSendRequest == 0 ){//bHttpSendRequestが0の場合はインターネットに接続されいないので、エラーを返す。
                return -106;//106:ERR_INTERNET_DISCONNECTED
        }

        //404や403エラーが発生していないか、を確認する。
                                                                //char BufSizeText[1000];
                                                                //DWORD BufSizeTextSize = 1000;
        DWORD StatusCode , StatusCode_Size = sizeof(DWORD);
        BOOL bHttpQueryInfo_STATUS = HttpQueryInfo(                        //エラーコードを数値として返してくれる。
                        hHttpRequest,
                        HTTP_QUERY_STATUS_CODE | HTTP_QUERY_FLAG_NUMBER ,        //「HTTP_QUERY_FLAG_NUMBER」を指定しなかった場合、文字列として返されるので、char型の配列をバッファに用意すればいい。
                        &StatusCode,                //BufSizeText                                        //「HTTP_QUERY_FLAG_NUMBER」を指定しない場合(&の有無に注意)
                        &StatusCode_Size,        //&BufSizeTextSize                                //「HTTP_QUERY_FLAG_NUMBER」を指定しない場合
                        NULL);

        if( StatusCode != HTTP_STATUS_OK ){
                //エラー処理

                //リソースの解放
                InternetCloseHandle(hHttpRequest);//「HttpQueryInfo()」および「InternetReadFile()」は「InternetCloseHandle()」の必要は無い。
                InternetCloseHandle(hHttpSession);
                InternetCloseHandle(hInternet);

                //一回試しただけだが、106エラーは検出できなかった。
                //(おそらくサーバーから応答の無いエラーは検出できないと考えられる。)
                //(WinInet.hを見れば分かるが、106エラーは定義すらされていない。検出できる訳が無かった。)
                if(StatusCode==403){
                        return -403;                        //404エラー
                }else if(StatusCode==404){
                        return -404;                        //403エラー
                }else{
                        return -1;                                //その他のエラーについては、今回扱わないので全て-1とする。「return StatusCode;」あるいは「「return (-1*StatusCode);」」としてもよかったのだが、今回は他の関数との都合でこのようにした。
                }
        }else{
                //ダウンロード処理。

                //ファイルのダウンロードに必要とされるバッファのサイズを確認する。
                DWORD RequiredBufSize , RequiredBufSize_Size = sizeof(DWORD);
                BOOL bHttpQueryInfo_ContentLength = HttpQueryInfo(                        //エラーコードを数値として返してくれる。
                                hHttpRequest,
                                HTTP_QUERY_CONTENT_LENGTH | HTTP_QUERY_FLAG_NUMBER ,
                                &RequiredBufSize,                        
                                &RequiredBufSize_Size,                
                                NULL);

                //必要なサイズだけメモリを確保する。
                char *Buf_main = (char *)malloc(RequiredBufSize*sizeof(char));

                char Buf_SaveName[200];
                sprintf_s( Buf_SaveName , sizeof(Buf_SaveName) , "%s\\%s" , SaveDirectory , SaveName );//保存するファイル名の生成
                FILE *file;
                fopen_s(&file, Buf_SaveName ,"wb");

                DWORD ReadSize;        //一回の操作で読みだされたサイズ
                DWORD ReadSize_sum=0;        //読み出しサイズの合計

                // コンテンツの内容を取得
                do{
                        BOOL bInternetReadFile = InternetReadFile(
                                hHttpRequest,
                                Buf_main,
                                RequiredBufSize,//        BufSize,
                                &ReadSize);

                        //ブレークポイント掛けて、物理的にネットケーブルを抜き差しして、HttpSendRequestはエラー無しで通し、InternetReadFileでエラーを出そうとしたけど、出ないから、
                        //こっちのエラー処理は不要。(HttpSendRequestだけでokと言う事)
                        //実際にファイルの保存までやってみたけど、mp3が正しく保存されている。
                        //恐らくだが、HttpSendRequestが成功した時点でダウンロードは全て完了している。
                        //ただし、
                        //バッファ一回のループでダウンロードできなかったり、サーバー側が分割してファイルを送信してくる場合には、どうなるか分からないので、一応確認だけしておく。
                        if( bInternetReadFile == 0 ){//bInternetReadFileが0の場合はインターネットに接続されいないので、エラーを返す。
                                free(Buf_main);
                                return -106;//106:ERR_INTERNET_DISCONNECTED
                        }

                        ReadSize_sum += ReadSize;

                        //ファイルへの書き出し。
                        fwrite(Buf_main,ReadSize,1,file);//fwrite(&Buf_main,ReadSize,1,file);としても誤って動いてしまうし、普通に再生もできるが、Chromeでダウンロードしたファイルとバイナリエディタで比較すると、ファイルの先頭と末尾の辺りにゴミが混じるので注意。

                }while(ReadSize!=0);//一回で読みだせるとは限らないので、ループを回す。

                fclose(file);
                free(Buf_main);

                if(ReadSize_sum != RequiredBufSize){
                        //「HttpQueryInfo()」で取得したファイルサイズと、実際に読みだしたファイルサイズが違う場合はエラーを返す。
                        //もし、サーバーからの応答が遅い???などの理由で上手く行かない場合は、上記の「do{}while();」文に、
                        //(必要であれば「Sleep();」を挟みながら、)サイズが一致するまでループを回すのもありだと思う。
                        //(当然だが、試行回数に制限を入れておかないと、無限ループに陥る可能性があるので注意。)
                        //ただ、自分の環境では、そのような事例はまだ無いので、実装はしない。
                        return -1;
                }
        }

        InternetCloseHandle(hHttpRequest);//「HttpQueryInfo()」および「InternetReadFile()」については「InternetCloseHandle()」する必要は無い。
        InternetCloseHandle(hHttpSession);
        InternetCloseHandle(hInternet);

        return 0;
}

ネタ元

ShiftJisとUTF8間のコード変換(VC++)

VC
char* szShiftJis = "雨にも負けず、風にも負けず。";
char bufUTF8[MAX_PATH];
char bufShiftJis[MAX_PATH];


void ShiftJisToUTF8()
{
    wchar_t bufUnicode[MAX_PATH];
    
    // まずUniocdeに変換する
    // サイズを計算する
    int iLenUnicode = MultiByteToWideChar(CP_ACP, 0, szShiftJis, strlen(szShiftJis)+1, 
                                                  NULL, 0);
    if (iLenUnicode <= sizeof(bufUnicode)/sizeof(bufUnicode[0]))
    {
        MultiByteToWideChar(CP_ACP, 0, szShiftJis, strlen(szShiftJis)+1, bufUnicode, MAX_PATH);
        // 次に、UniocdeからUTF8に変換する
        // サイズを計算する
        int iLenUtf8 = WideCharToMultiByte(CP_UTF8, 0, bufUnicode, iLenUnicode, NULL, 0, 
                                                 NULL, NULL);
        if (iLenUtf8 <= sizeof(bufUTF8))
        {
            WideCharToMultiByte(CP_UTF8, 0, bufUnicode, iLenUnicode, bufUTF8, sizeof(bufUTF8), 
                                     NULL, NULL);
        }
    }
}

void UTF8ToShiftJis()
{
    wchar_t bufUnicode[MAX_PATH];
    
    // まずUniocdeに変換する
    // サイズを計算する
    int iLenUnicode = MultiByteToWideChar(CP_UTF8, 0, bufUTF8, strlen(bufUTF8)+1, NULL, 0);
    if (iLenUnicode <= sizeof(bufUnicode)/sizeof(bufUnicode[0]))
    {
        MultiByteToWideChar(CP_UTF8, 0, bufUTF8, strlen(bufUTF8)+1, bufUnicode, MAX_PATH);
        // 次に、UniocdeからShiftJisに変換する
        // サイズを計算する
        int iLenUtf8 = WideCharToMultiByte(CP_ACP, 0, bufUnicode, iLenUnicode, NULL, 0, 
                                                  NULL, NULL);
        if (iLenUtf8 <= sizeof(bufUTF8))
        {
            WideCharToMultiByte(CP_ACP, 0, 
                                     bufUnicode, iLenUnicode, 
                                     bufShiftJis, sizeof(bufShiftJis), 
                                     NULL, NULL);
        }
    }
}

ネタ元

WinInetによるインターネット上ファイルの読み込みサンプル

MFC

超簡単サンプルです。ファイルの全部読み込みとか なーんもやってない。

	{
		LPTSTR lpszBuf=(LPTSTR)GlobalAlloc(GPTR,1024);
		/* ハンドル作成 */
		HINTERNET hInet=InternetOpen(_T("TEST"),INTERNET_OPEN_TYPE_DIRECT,NULL,NULL,0);
		/* URLオープン */
		HINTERNET hFile=InternetOpenUrl(hInet,
			_T("http://stocks.finance.yahoo.co.jp/stocks/detail/?code=8411.T"),
			NULL,0,INTERNET_FLAG_RELOAD,0);
		/* ファイル読み込み */
		DWORD dwSize;
		InternetReadFile(hFile,lpszBuf,1023,&dwSize);

		/* 終了処理 */
		InternetCloseHandle(hFile);
		InternetCloseHandle(hInet);

		GlobalFree(lpszBuf);
	}

ネタ元

ワンクリック注文したKindleを購入後にキャンセルする方法

1.AmazonのユーザIDにログインして「カスタマーサービスに連絡」のページに行く。

2.お問い合わせの種類を選択してくださいという欄に表示されているキャンセルしたい商品を選択する。

3.お問い合わせ内容を選択してくださいという欄でお問い合わせ内容の「返品、交換、返金」を選択する。

4.問い合わせ方法として電話・チャット・メールのどれかを選択する。

あとは間違って購入してしまったので返金して欲しい旨を伝えるだけです。


ネタ元

GetWindowPlacement()で取得した座標でウインドウ位置戻すならSetWindowPlacement()が必須

GetWindowPlacementはタスクバーをスクリーンから分離します。つまり、スクリーンの一部とは考えません。
一方SetWindowPos関数はタスクバーをスクリーンの一部と考えて動作します。

なのでGetWindowPlacement の情報から位置を復元するにはSetWindowPlacement を使わなければならない、だそうです。SetWindowPos関数を使ってはダメ

ネタ元

WordPressでパーマリンクを設定してもページが404not foundになる時の対処法

wordpress

.htaccessにmod_rewriteを使えるように設定書く

wordpressのフォルダがwpの場合

# BEGIN WordPress
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteBase /wp/
RewriteRule ^indexÅ_.php$ - [L]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule . /wp/index.php [L]
</IfModule>
# END WordPress

文字コードはutf-8でね

ネタ元

MFC メモリデバイスコンテキストに文字列を出力

MFC
/*************************************************
関数名 DrawStringToHDC
機能   メモリデバイスコンテキストに文字列を出力
iXsize : 出力画像の幅(Width)
iYpos  : 縦方向の出力位置
*************************************************/
void DrawStringToHDC(HDC hdc, CStringW csw, int iXsize,int iYpos)
{
    wchar_t wct[512];
    SIZE sz;
    ZeroMemory(&wct, 512);
    wcscpy_s(wct, csw);
    //中央に描画する
    GetTextExtentPoint32W(hdc, wct, lstrlenW(wct), &sz);
    TextOutW(hdc, (iXsize - sz.cx) / 2, iYpos, wct, lstrlenW(wct));
}

ネタ元