使用cpprestsdk发送含字符串与图片的REST POST请求遇阻
使用cpprestsdk实现带文件的POST注册请求问题
我正在用cpprestsdk开发对接外部API的桌面客户端,卡在注册功能的POST请求环节——这个请求需要同时发送字符串参数和一张图片。
我计划通过以下函数实现注册:
bool POSTUser(string_t &token, string_t &name, string_t &email, string_t &phone, string_t &photoPath);
我考虑用web::http::client::http_client::request的重载方法(服务器响应为JSON格式)结合filestream,但不知道怎么和JSON结合,也搞不懂模板中_CharType的含义。
服务器API参数要求
- name - 字符串
- email - 字符串
- phone - 字符串
- position_id - 字符串
- photo - 用户照片,格式需为jpg/jpeg
请求URL示例:https://server.server/api/v1/users
curl请求示例
$curl --form "photo=@example/photo.jpg;" \ --form name=Jhon \ --form email=jhon@example.com \ --form phone=+380955388485 \ --form position_id=2 \ https://server.server/api/v1/users
JavaScript请求示例
var formData = new FormData(); // 文件来自input type='file' var fileField = document.querySelector('input[type="file"]'); formData.append('position_id', 2); formData.append('name', 'Jhon'); formData.append('email', 'Jhon@gmail.com'); formData.append('phone', '+380955388485'); formData.append('photo', fileField.files[0]); fetch('https://server.server/api/v1/users', { method: 'POST', body: formData, headers: { 'Token': token, // 通过GET api/v1/token接口获取token }, }).then(function(response) { return response.json(); }) .then(function(data) { console.log(data); if(data.success) { // 处理成功响应 } else { // 处理服务器错误 } }).catch(function(error) { // 处理网络错误 });
解决方案
1. 关于_CharType的说明
cpprestsdk里的模板参数_CharType用来指定字符编码,通常是wchar_t(对应string_t,也就是utility::string_t,默认UTF-16)或者char(对应std::string)。你代码里用的string_t就是wchar_t类型字符串,直接用默认的web::http::client::http_client(基于wchar_t的实例)就行,不用额外处理。
2. 构造multipart/form-data请求(无需JSON)
注意:服务器接收的是multipart/form-data格式(看curl和JS示例都是用FormData),JSON没法直接传文件,所以不用纠结和JSON结合,直接构造表单请求即可。
以下是POSTUser函数的核心实现代码:
#include <cpprest/http_client.h> #include <cpprest/filestream.h> #include <cpprest/json.h> using namespace web; using namespace web::http; using namespace web::http::client; using namespace utility; bool POSTUser(string_t &token, string_t &name, string_t &email, string_t &phone, string_t &photoPath) { try { http_client client(U("https://server.server/api/v1/users")); // 构造POST请求 http_request request(methods::POST); // 设置Token请求头 request.headers().add(U("Token"), token); // 创建multipart表单容器 auto form_data = http_multipart_content(); // 添加字符串参数 form_data.add(http_content_part(U("name"), name)); form_data.add(http_content_part(U("email"), email)); form_data.add(http_content_part(U("phone"), phone)); form_data.add(http_content_part(U("position_id"), U("2"))); // 可根据需求将position_id改为函数参数传入 // 读取图片文件并添加到表单 concurrency::streams::istream file_stream = concurrency::streams::file_stream<string_t>::open(photoPath).get(); http_content_part file_part; file_part.set_content_disposition(U("form-data"), U("photo")); file_part.set_content_type(U("image/jpeg")); // jpg/jpeg对应的MIME类型 file_part.set_stream(file_stream); form_data.add(file_part); // 将表单设置为请求体 request.set_body(form_data); // 发送请求并同步等待响应 http_response response = client.request(request).get(); // 解析JSON响应 json::value response_json = response.extract_json().get(); // 根据服务器返回的success字段判断结果 if (response_json.has_field(U("success")) && response_json[U("success")].as_bool()) { return true; } else { // 可打印错误信息 if (response_json.has_field(U("message"))) { ucout << U("注册失败:") << response_json[U("message")].as_string() << std::endl; } return false; } } catch (const std::exception &e) { // 处理网络错误、文件读取失败等异常 std::cerr << "异常:" << e.what() << std::endl; return false; } }
关键提示
- 必须用
http_multipart_content构造请求体,这是传输文件+字符串参数的标准方式。 - 打开文件时用
concurrency::streams::file_stream,同步场景下用.get()等待操作完成。 string_t是UTF-16字符串,字面量要加U前缀(比如U("name"))。- 图片的Content-Type要匹配格式,jpg/jpeg对应
image/jpeg。
内容的提问来源于stack exchange,提问作者Naxel
相关产品推荐
相关产品推荐

