|
|
VC++以FORM形式提交urlencode
在 VC++ 里用表单方式(application/x-www-form-urlencoded)提交 HTTP 请求。下面给你一个典型实现思路和示例代码(用 WinHTTP,更常见、也更现代一些;如果你需要 WinINet 或 MFC CInternet 版本也可以再写)。 思路概括 - 构造表单字符串:key1=value1&key2=value2,各值做 URL 编码。
- 设置请求头:Content-Type: application/x-www-form-urlencoded;charset=UTF-8
- 用 WinHTTP/WinINet 发送 POST 请求,写入表单数据,读取响应。
下面示例用 WinHTTP + 简单的 URL 编码函数。 1. 简单 URL 编码函数 (C++)- #include <windows.h>
- #include <string>
- #include <sstream>
- #include <iomanip>
- std::string UrlEncode(const std::string& value)
- {
- std::ostringstream escaped;
- escaped.fill('0');
- escaped << std::hex << std::uppercase;
- for (unsigned char c : value)
- {
- if ((c >= 'A' && c <= 'Z') ||
- (c >= 'a' && c <= 'z') ||
- (c >= '0' && c <= '9') ||
- c == '-' || c == '_' || c == '.' || c == '~')
- {
- escaped << c;
- }
- else if (c == ' ')
- {
- escaped << '+'; // 表单里空格常用 +
- }
- else
- {
- escaped << '%' << std::setw(2) << int(c);
- }
- }
- return escaped.str();
- }
复制代码 2. 使用 WinHTTP 发送 application/x-www-form-urlencoded POST
- #include <windows.h>
- #include <winhttp.h>
- #include <string>
- #include <iostream>
- #pragma comment(lib, "winhttp.lib")
- bool PostFormUrlEncoded(
- const std::wstring& host,
- INTERNET_PORT port,
- const std::wstring& path,
- const std::string& formData, // 已经 key=value&key2=value2
- std::string& responseBody // 输出响应体
- )
- {
- bool result = false;
- HINTERNET hSession = NULL, hConnect = NULL, hRequest = NULL;
- // 1. 打开会话
- hSession = WinHttpOpen(L"VC++ Form Client/1.0",
- WINHTTP_ACCESS_TYPE_DEFAULT_PROXY,
- WINHTTP_NO_PROXY_NAME,
- WINHTTP_NO_PROXY_BYPASS, 0);
- if (!hSession) goto cleanup;
- // 2. 连接服务器
- hConnect = WinHttpConnect(hSession, host.c_str(), port, 0);
- if (!hConnect) goto cleanup;
- // 3. 打开请求 (POST)
- hRequest = WinHttpOpenRequest(
- hConnect,
- L"POST",
- path.c_str(),
- NULL,
- WINHTTP_NO_REFERER,
- WINHTTP_DEFAULT_ACCEPT_TYPES,
- 0 // 如果是 https 则用 WINHTTP_FLAG_SECURE
- );
- if (!hRequest) goto cleanup;
- // 4. 设置头:Content-Type
- LPCWSTR headers =
- L"Content-Type: application/x-www-form-urlencoded; charset=UTF-8\r\n";
- if (!WinHttpAddRequestHeaders(hRequest, headers,
- (ULONG)-1L, WINHTTP_ADDREQ_FLAG_ADD))
- goto cleanup;
- // 5. 发送请求 + 写入表单数据
- if (!WinHttpSendRequest(
- hRequest,
- WINHTTP_NO_ADDITIONAL_HEADERS,
- 0,
- (LPVOID)formData.data(),
- (DWORD)formData.size(),
- (DWORD)formData.size(),
- 0))
- goto cleanup;
- if (!WinHttpReceiveResponse(hRequest, NULL))
- goto cleanup;
- // 6. 读取响应
- for (;;)
- {
- DWORD dwSize = 0;
- if (!WinHttpQueryDataAvailable(hRequest, &dwSize) || dwSize == 0)
- break;
- std::string buffer(dwSize, '\0');
- DWORD dwRead = 0;
- if (!WinHttpReadData(hRequest, &buffer[0], dwSize, &dwRead) || dwRead == 0)
- break;
- buffer.resize(dwRead);
- responseBody += buffer;
- }
- result = true;
- cleanup:
- if (hRequest) WinHttpCloseHandle(hRequest);
- if (hConnect) WinHttpCloseHandle(hConnect);
- if (hSession) WinHttpCloseHandle(hSession);
- return result;
- }
复制代码3. 组合表单并调用示例 假设你要提交: - phone = 13812345678
- timestamp = "2025-11-18T10:00:00Z"
- nonce = "abc123xyz"
- sign = "someSignValue"
- void TestPost()
- {
- std::string phone = UrlEncode("13812345678");
- std::string timestamp = UrlEncode("2025-11-18T10:00:00Z");
- std::string nonce = UrlEncode("abc 123 xyz"); // 带空格示例
- std::string sign = UrlEncode("someSignValue");
- std::string form =
- "phone=" + phone + "&"
- "timestamp=" + timestamp + "&"
- "nonce=" + nonce + "&"
- "sign=" + sign;
- std::string resp;
- bool ok = PostFormUrlEncoded(
- L"localhost", // 服务器域名
- 8080, // 端口
- L"/auth/sendCode", // 路径
- form,
- resp
- );
- if (ok)
- std::cout << "Response: " << resp << std::endl;
- else
- std::cout << "Request failed" << std::endl;
- }
复制代码4. 编译 / 链接要点 - 工程里要包含:
- 链接库:
- winhttp.lib(在 VC++ 的链接器设置里添加,或者用 #pragma comment(lib, "winhttp.lib"))
|
|