首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> C語言 >> VC >> VC 教學

VC++ WinInet 實現 HTTP POST 請求:表單提交與 Content-Type 設定詳解

     編輯:VC 教學

使用 WinInet (Windows Internet API) 模擬瀏覽器表單提交 (HTTP POST),關鍵在於正確設定 Content-Type: application/x-www-form-urlencoded 標頭,並對表單數據進行 URL 編碼。本文提供 MFC CInternetSession 封裝版與純 SDK 版雙重實現代碼。

核心要點

  • 標頭: Content-Type: application/x-www-form-urlencoded (必須,否則 IIS ASP/ASP.NET 不會填充 Request.Form 集合)。
  • 數據格式: name=value&name2=value2,空格編碼為 + 或 %20,特殊字元 %+十六進位 (如 & → %26)。
  • 編碼函數: 可用 CString::UrlEncode (MFC/ATL) 或自寫 URL Encode。

MFC 版實現 (推薦,自動管理連接/緩衝)

bool HttpPostForm(const CString& server, const CString& action, const CString& formData, CString& response) {
    CString headers = _T("Content-Type: application/x-www-form-urlencoded");
    // formData 範例: "username=admin&password=123456&submit=%E7%99%BB%E5%BD%95"

    CInternetSession session(_T("MyApp/1.0"));
    CHttpConnection* pConn = NULL;
    CHttpFile* pFile = NULL;

    try {
        pConn = session.GetHttpConnection(server, INTERNET_DEFAULT_HTTP_PORT);
        pFile = pConn->OpenRequest(CHttpConnection::HTTP_VERB_POST, action);
        // 發送請求
        BOOL ok = pFile->SendRequest(headers, (LPVOID)(LPCTSTR)formData, formData.GetLength());
        if (!ok) { delete pFile; delete pConn; return false; }

        // 讀取回應
        CString line;
        response.Empty();
        while (pFile->ReadString(line)) response += line + _T("\n");
    } catch (CInternetException* e) {
        TCHAR err[256]; e->GetErrorMessage(err, 255);
        TRACE(_T("WinInet Error: %s\n"), err);
        e->Delete();
        if (pFile) delete pFile;
        if (pConn) delete pConn;
        return false;
    }

    delete pFile;
    delete pConn;
    return true;
}

// 調用
CString resp;
HttpPostForm(_T("api.example.com"), _T("/login"), _T("user=admin&pass=123"), resp);

純 SDK 版實現 (無 MFC 依賴)

bool HttpPostSDK(const char* server, const char* action, const char* formData) {
    HINTERNET hSession = InternetOpen("MyApp/1.0", INTERNET_OPEN_TYPE_PRECONFIG, NULL, NULL, 0);
    if (!hSession) return false;

    HINTERNET hConnect = InternetConnect(hSession, server, INTERNET_DEFAULT_HTTP_PORT,
                                         NULL, NULL, INTERNET_SERVICE_HTTP, 0, 0);
    if (!hConnect) { InternetCloseHandle(hSession); return false; }

    const char* accept = "Accept: */*";
    HINTERNET hRequest = HttpOpenRequest(hConnect, "POST", action, NULL, NULL, &accept, 0, 0);
    if (!hRequest) { InternetCloseHandle(hConnect); InternetCloseHandle(hSession); return false; }

    const char* headers = "Content-Type: application/x-www-form-urlencoded";
    BOOL ok = HttpSendRequest(hRequest, headers, strlen(headers), (LPVOID)formData, strlen(formData));

    // 讀取回應 (略)
    char buf[1024]; DWORD read;
    while (InternetReadFile(hRequest, buf, sizeof(buf)-1, &read) && read) { buf[read]=0; OutputDebugStringA(buf); }

    InternetCloseHandle(hRequest);
    InternetCloseHandle(hConnect);
    InternetCloseHandle(hSession);
    return ok;
}

URL 編碼輔助函數 (無 ATL/MFC 時)

CString UrlEncode(const CString& src) {
    CString dest;
    for (int i=0; i

常見問題

  1. HTTPS: INTERNET_DEFAULT_HTTPS_PORT (443),InternetConnect 第三參數改 443,HttpOpenRequest 加 INTERNET_FLAG_SECURE。
  2. 大數據: HttpSendRequestEx + InternetWriteFile 分塊寫入。
  3. Cookie/Session: InternetGetCookie/SetCookie 或讓 CInternetSession 自動管理。
  4. 超時: InternetSetOption(INTERNET_OPTION_CONNECT_TIMEOUT/RECEIVE_TIMEOUT)。

WinInet 是 Windows 系統級 HTTP 客戶端,無需第三方庫 (如 libcurl),部署極輕量,適合簡單 REST API 呼叫、表單提交、檔案上傳/下載。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved