松鼠的博客

导航

在VC中WININET如何使用HTTP的POST方法

SUMMARY
To properly simulate a Form submission using WinInet, you need to send a header that indicates the proper Content-Type. For Forms, the proper Content-Type header is: Content-Type: application/x-www-form-urlencoded
                 
MORE INFORMATION
     In many cases, the server does not respond appropriately if a Content-Type is not specified. For example, the Active Server Pages component of IIS 3.0 actually checks this header specifically for 'application/x-www-form- urlencoded' before adding form variables to the "Request.Form" object. This MIME/Content-Type indicates that the data of the request is a list of URL- encoded form variables. URL-encoding means that space character (ASCII 32) is encoded as ' ', special character such '!' encoded in hexadecemal form as '!'.

Here is a snippet of code that uses the MFC WinInet classes to simulate a Form POST request:

CString strHeaders = _T("Content-Type: application/x-www-form-urlencoded");
// URL-encoded form variables -
// name = "John Doe", userid = "hithere", other = "P&Q"
CString strFormData = _T("name=John Doe&userid=hithere&other=P&Q");
CInternetSession session;
CHttpConnection
* pConnection = session.GetHttpConnection(_T("ServerNameHere"));
CHttpFile
* pFile = pConnection->OpenRequest(CHttpConnection::HTTP_VERB_POST,_T("FormActionHere"));
BOOL result 
= pFile->SendRequest(strHeaders,(LPVOID)(LPCTSTR)strFormData, strFormData.GetLength());


Without MFC, the same code translates to straight SDK calls as follows:

static 

TCHAR hdrs[] = _T("Content-Type: application/x-www-form-urlencoded");


static

TCHAR frmdata[] = _T("name=John Doe&userid=hithere&other=P&Q");
statuc TCHAR accept[] 
= _T("Accept: */*");
    
// for clarity, error-checking has been removed
HINTERNET hSession = InternetOpen("MyAgent",INTERNET_OPEN_TYPE_PRECONFIG, NULL, NULL, 0);
HINTERNET hConnect 
= InternetConnect(hSession, _T("ServerNameHere"),
                                     INTERNET_DEFAULT_HTTP_PORT,
                                     NULL,
                                     NULL,
                                     INTERNET_SERVICE_HTTP,
                                     
0,
                                     
1);
HINTERNET hRequest 
= HttpOpenRequest(hConnect, 
                                     
"POST",
                                     _T(
"FormActionHere"), 
                                     NULL, 
                                     NULL, 
                                     accept, 
                                     
0
                                     
1);
HttpSendRequest(hRequest, 
                hdrs, 
                strlen(hdrs), 
                frmdata, 
                strlen(frmdata));


// close any valid internet-handles

我这里有一段程序,用来在一个对话框里显示出一次http     request的原始信息,不过使用Inet     API做的,希望能有帮助。   

void CHTTPRequestDlg::OnButtonRequest() 
{
    UpdateData(TRUE);   
    HINTERNET hInternet 
= InternetOpen("Mozilla/4.0 (compatible; MSIE 5.0; Windows NT 5.0)"
                                        INTERNET_OPEN_TYPE_DIRECT,
                                        NULL,
                                        NULL,
                                        NULL);   
    HINTERNET hSession 
= InternetConnect(hInternet,
                                        m_strHost,   
                                        m_nPort,
                                        
"username",
                                        
"password",   
                                        INTERNET_SERVICE_HTTP,
                                        
0,
                                        
0);   
    
char* szAccept[] = {"*/*",NULL};
    CString strVerb;
    m_comboVerb.GetWindowText(strVerb);   
    HINTERNET hRequest 
= HttpOpenRequest(hSession,
                                        strVerb,
                                        m_strObject,
                                        NULL,
                                        NULL,
                                        (LPCSTR
*)szAccept,
                                        
0,
                                        
0);   
    
struct   
    
{   
        
char* Language;   
        
char* Encoding;   
        
char* ContentType;   
    }
Headers = {"Accept-Language:zh-cn\r\n",
                
"Accept-Encoding:gzip,deflate\r\n",   
                
"Content-Type:application/x-www-form-urlencoded\r\n"}
;
    
    
if(m_bLanguage)   
    
{
        HttpAddRequestHeaders(hRequest,
                                Headers.Language, 
                                
-1,
                                HTTP_ADDREQ_FLAG_ADD
|HTTP_ADDREQ_FLAG_REPLACE);   
    }

    
if(m_bEncoding)   
    
{
        HttpAddRequestHeaders(hRequest,
                                Headers.Encoding, 
                                
-1,
                                HTTP_ADDREQ_FLAG_ADD
|HTTP_ADDREQ_FLAG_REPLACE);   
    }

    
if(m_bContentType)   
    
{
        HttpAddRequestHeaders(hRequest,
                                Headers.ContentType,
                                
-1,
                                HTTP_ADDREQ_FLAG_ADD
|HTTP_ADDREQ_FLAG_REPLACE);   
    }

    LPCSTR lpAddHeader 
= NULL;
    LPCSTR lpContent 
= NULL;   

    
if(m_strHeaders.GetLength())   
    
{   
        
if(m_strHeaders.Right(2!= "\r\n")   
        
{
            m_strHeaders
+="\r\n";   
        }

        lpAddHeader 
= (LPCSTR)m_strHeaders;   
    }
   
    
if(m_strContent.GetLength() && (strVerb == "POST" || strVerb == "PUT"))   
    
{
        lpContent 
= (LPCSTR)m_strContent;   
    }

    HttpSendRequest(hRequest,
                    lpAddHeader,
                    
-1,
                    (LPVOID)lpContent,
                    m_strContent.GetLength());   
    
    m_editContentGot.SetSel(
0,-1);   
    m_editContentGot.ReplaceSel(
"");   
    
    LPSTR lpszData;        
//buffer for the data   
    DWORD dwSize;        //size of the data available   
    DWORD dwDownloaded; //size of the downloaded data   
    
    
//Set the cursor to an hourglass.   
    SetCursor(LoadCursor(NULL,IDC_WAIT));   
    
    
// This loop handles reading the data.   
    while(1)   
    
{   
        
// The call to InternetQueryDataAvailable determines the amount of 
        
// data available to download.   
        if (!InternetQueryDataAvailable(hRequest,&dwSize,0,0))   
        
{   
            SetCursor(LoadCursor(NULL,IDC_ARROW));   
            
break;   
        }
   
        
else   
        
{     
            
// Allocates a buffer of the size returned by InternetQueryDataAvailable   
            lpszData = new char[dwSize+1];   
            
            
// Reads the data from the HINTERNET handle.   
            if(!InternetReadFile(hRequest,(LPVOID)lpszData,dwSize,&dwDownloaded))   
            
{   
                delete[] lpszData;   
                
break;   
            }
   
            
else   
            
{   
                
// Adds a null terminator to the end of the data buffer   
                lpszData[dwDownloaded]='\0';   
                
                
int nLen = m_editContentGot.GetWindowTextLength();   
                m_editContentGot.SetSel(nLen
-1, nLen-1);   
                m_editContentGot.ReplaceSel(lpszData);   
                
                
// Delete the two buffers   
                delete[] lpszData;   
                
                
// Check the size of the remaining data.   If it is zero, break.   
                if (dwDownloaded == 0)   
                
{
                    
break;   
                }

            }

        }
   
    }
   
    
    
// Close the HINTERNET handle   
    InternetCloseHandle(hRequest);   
    InternetCloseHandle(hSession);   
    InternetCloseHandle(hInternet);   
    
    
// Set the cursor back to an arrow   
    SetCursor(LoadCursor(NULL,IDC_ARROW));   
}


==========================================

使用MFC示例如下:   
    首先设置m_strRequest请求字符串       eg."name=aaa&pass=bbb";               
                    m_strServerName     服务器名称或者IP       eg."www.yahoo.com"   
                    m_strObjectName     请求文件位置     eg.     "pub/aaa.asp"   
        请求的结果存放在m_strHtml中   

void func()
{   
    CInternetSession m_InetSession(
"session");
    CHttpConnection 
*pServer = NULL;
    CHttpFile
* pFile = NULL;   
    
try
    
{   
        INTERNET_PORT nPort;
        nPort
=80;
        pServer 
= m_InetSession.GetHttpConnection(m_strServerName, nPort);
        pFile 
= pServer->OpenRequest(CHttpConnection::HTTP_VERB_POST,m_strObjectName);
        
char szHeaders[100];
        strcpy(szHeaders,
"Accept: text*/*\r\nContent-Type: application/x-www-form-urlencoded");
        pFile
->AddRequestHeaders(szHeaders);
        
        pFile
->SendRequestEx(m_strRequest.GetLength());   
        pFile
->WriteString(m_strRequest);//重要-->m_Request 中有"name=aaa&name2=BBB&"
        pFile->EndRequest();
        DWORD dwRet;
        pFile
->QueryInfoStatusCode(dwRet);
        CString str;
        
        m_Mutex.Lock();
        m_strHtml
="";
        
char szBuff[1024];

        
if (dwRet == HTTP_STATUS_OK)
        
{
            UINT nRead;   
            
while ((nRead = pFile->Read(szBuff,1023))>0)   
            
{   
                m_strHtml 
+= CString(szBuff,nRead);   
            }

        }

        m_Mutex.Unlock();   
        
        delete pFile;   
        delete pServer;   
    }
   
    
catch (CInternetException* e)
    
{   
        CString s;   
        s.Format(
"Internet Exception\r\nm_dwError%u,m_dwContextError%u",e->m_dwError,e->m_dwContext);   
        AfxMessageBox(s);   
        
//catch errors from WinInet   
    }
   
}


============================

1、获得WebBrowser     Control的DWebBrowserEvents2::DocumentComplete事件   
    2、在DWebBrowserEvents2::DocumentComplete事件中根据IWebBrowser2::Document获得IHTMLDocument2   
    3、IHTMLDocument2::forms得到IHTMLElementCollection   
    4、在IHTMLElementCollection中根据name、tagName、ID得到指定的IHTMLElement   
    5、从IHTMLElement得到IHTMLFormElement   
    6、执行IHTMLFormElement::submit

posted on 2008-12-03 15:19  Xproer-松鼠  阅读(6230)  评论(0编辑  收藏  举报