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

    技术2022-05-19  20

    SUMMARYTo 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

     


    最新回复(0)