解説
Wininet.dllを利用して掲示板に投稿する方法。URLを変えることでHTTPとHTTPS(SSL)に対応する。ここではポストした結果はファイルとして保存している。
使用例
DownloadWithPostTest(_T("https://www.dinop.com/testssl.html"),_T("aaa=bbb&ccc=ddd"),"c:\\aaa.txt");
ソースコード
#include "atlfile.h"
#include "wininet.h"
#pragma comment(lib,"wininet.lib")
bool DownloadWithPostTest(LPCTSTR pszURL,LPCTSTR pszPostData,LPCTSTR pszLocalFile,DWORD dwBuffSize=1024)
{
TCHAR pszAccept[] = _T("Accept: */*");
TCHAR pszContentType[] = _T("Content-Type: application/x-www-form-urlencoded");
BOOL ret;
DWORD dwReadSize;
DWORD dwWrittenSize;
BYTE* pcbBuff;
HRESULT hr;
HINTERNET hInternet;
HINTERNET hConnect;
HINTERNET hRequest;
TCHAR lpszHostName[256];
TCHAR lpszScheme[256];
TCHAR lpszUserName[256];
TCHAR lpszPassword[256];
TCHAR lpszUrlPath[1024];
TCHAR lpszExtraInfo[1024];
int nFind;
CAtlFile cFile;
CAtlString strPath;
URL_COMPONENTS sComponents;
//////////////////////////////
// URLからサーバー名やポート番号などを取得
//
ZeroMemory(&sComponents,sizeof(URL_COMPONENTS));
sComponents.dwStructSize = sizeof(URL_COMPONENTS);
sComponents.lpszHostName = lpszHostName;
sComponents.dwHostNameLength = sizeof(lpszHostName) / sizeof(TCHAR);
sComponents.lpszScheme = lpszScheme;
sComponents.dwSchemeLength = sizeof(lpszScheme) / sizeof(TCHAR);
sComponents.lpszUserName = lpszUserName;
sComponents.dwUserNameLength = sizeof(lpszUserName) / sizeof(TCHAR);
sComponents.lpszPassword = lpszPassword;
sComponents.dwPasswordLength = sizeof(lpszPassword) / sizeof(TCHAR);
sComponents.lpszUrlPath = lpszUrlPath;
sComponents.dwUrlPathLength = sizeof(lpszUrlPath) / sizeof(TCHAR);
sComponents.lpszExtraInfo = lpszExtraInfo;
sComponents.dwExtraInfoLength = sizeof(lpszExtraInfo) / sizeof(TCHAR);
ret = ::InternetCrackUrl(pszURL,lstrlen(pszURL),ICU_ESCAPE,&sComponents);
if(ret == FALSE)
return false;
//////////////////////////////
// InternetCrackUrlはURLなどに含まれる"%20"などをデコード
// してしまうので、関数呼出時のURLのパスを使って接続する
// 変則的なサーバーは「/index.html?aaa=bbb」というURLに対
// してPOSTを要求することもあるので、それにも対応。
//
strPath = pszURL;
nFind = strPath.Find(lpszHostName);
if(nFind >= 0)
{
nFind = strPath.Find(_T("/"),nFind);
if(nFind >= 0)
strPath = strPath.Right(strPath.GetLength() - nFind);
}
if(nFind < 0)
{
strPath = lpszUrlPath;
strPath += lpszExtraInfo;
}
//バッファ確保
pcbBuff = new BYTE[dwBuffSize];
if(pcbBuff == NULL)
return false;
//////////////////////////////
// 接続開始
//
hInternet = ::InternetOpen(NULL,INTERNET_OPEN_TYPE_PRECONFIG,NULL,NULL,0);
hConnect = NULL;
if(hInternet)
hConnect = ::InternetConnect(hInternet,lpszHostName,sComponents.nPort,lpszUserName,lpszPassword,INTERNET_SERVICE_HTTP,0,0);
hRequest = NULL;
if(hConnect)
{
if(sComponents.nScheme == INTERNET_SCHEME_HTTPS)
hRequest = ::HttpOpenRequest(hConnect,_T("POST"),strPath,NULL,NULL,(LPCTSTR*)&pszAccept,INTERNET_FLAG_RELOAD | INTERNET_FLAG_SECURE | INTERNET_FLAG_NO_UI | INTERNET_FLAG_KEEP_CONNECTION,0);
else
hRequest = ::HttpOpenRequest(hConnect,_T("POST"),strPath,NULL,NULL,(LPCTSTR*)&pszAccept,INTERNET_FLAG_RELOAD | INTERNET_FLAG_NO_UI | INTERNET_FLAG_KEEP_CONNECTION,0);
}
ret = FALSE;
if(hRequest)
ret = ::HttpSendRequest(hRequest,pszContentType,lstrlen(pszContentType),(LPVOID)pszPostData,lstrlen(pszPostData));
//if(ret)
//{
// DWORD dwContentLength;
// dwContentLength = dwBuffSize;
// ret = ::HttpQueryInfo(hRequest,HTTP_QUERY_CONTENT_LENGTH,pcbBuff,&dwContentLength,NULL);
// if(ret)
// {
// ATLTRACE(_T("ダウンロードサイズは合計 %d Bytes\n"),dwContentLength);
// }
// else
// {
// ATLTRACE(_T("ダウンロードサイズは不明\n"),dwContentLength);
// }
// ret = TRUE;
//}
if(ret)
ret = SUCCEEDED(cFile.Create(pszLocalFile,GENERIC_WRITE,0,CREATE_ALWAYS)) ? TRUE : FALSE;
if(ret)
{
while(1)
{
::Sleep(0);
dwReadSize = 0;
ret = ::InternetReadFile(hRequest,pcbBuff,dwBuffSize,&dwReadSize);
if(ret == FALSE)
break;
if(dwReadSize == 0)
break;
hr = cFile.Write(pcbBuff,dwReadSize,&dwWrittenSize);
if(SUCCEEDED(hr))
continue;
ret = FALSE;
break;
}
}
hr = cFile.Flush();
cFile.Close();
if(hRequest)
::InternetCloseHandle(hRequest);
if(hConnect)
::InternetCloseHandle(hConnect);
if(hInternet)
::InternetCloseHandle(hInternet);
delete pcbBuff;
return (SUCCEEDED(hr) && ret) ? true : false;
}







