C++使用旧版libcurl通过multipart上传文件失败如何解决?
问题修复说明
存在的核心错误
- 重复提交同名字段:两次调用
curl_formadd使用相同的CURLFORM_COPYNAME值,第一次上传文件、第二次上传文件路径字符串,会导致服务端解析表单时字段冲突,无法正确识别文件内容。 - 错误添加表单Part头到全局HTTP头:
Content-Disposition是multipart表单内部单个文件块的请求头,不应该手动添加到全局HTTP请求头中,该操作会打乱libcurl自动生成的multipart请求结构,你实际请求中Content-Type出现在请求体前的错误位置就是该操作导致的,服务端无法正常解析表单内容。 - 基础语法错误:
- 未定义
ImageName、ImageNameWithPath变量类型,Url字符串未加双引号 - 调用
curl_easy_setopt设置地址时变量名拼写错误,将Url写成了Ulr - 响应变量名拼写不一致,定义的是
Reponse,传参用的是Response Content-Type值格式错误,正确的图片类型应为image/jpeg,不需要加(binary)后缀
- 未定义
- 缺失错误校验逻辑:未判断
curl_easy_perform、curl_formadd等接口的返回值,无法定位文件不存在、参数错误等基础问题。
修复后的可用代码
#include "curl/curl.h" #include <string> using namespace std; size_t WriteCallback(void * buffer, size_t size, size_t count, void * user) { ((string *) user)->append((char *) buffer, size * count); return size * count; } int main() { curl_global_init(CURL_GLOBAL_ALL); CURL * Curl = curl_easy_init(); if (!Curl) { curl_global_cleanup(); return -1; } CURLcode res; curl_easy_setopt(Curl, CURLOPT_FAILONERROR, 0L); curl_easy_setopt(Curl, CURLOPT_VERBOSE, 1L); struct curl_httppost * formpost = NULL; struct curl_httppost * lastptr = NULL; struct curl_slist * headerlist = NULL; // 禁用Expect: 100-continue,避免部分服务端不兼容 static const char buf[] = "Expect:"; headerlist = curl_slist_append(headerlist, buf); string ImageName = "myimage.jpg"; string ImageNameWithPath = "/this/location/right/here/" + ImageName; // 仅添加一次文件字段,表单字段名设为服务端要求的file,和你预期的结构一致 curl_formadd(&formpost, &lastptr, CURLFORM_COPYNAME, "file", CURLFORM_FILE, ImageNameWithPath.c_str(), CURLFORM_FILENAME, ImageName.c_str(), CURLFORM_CONTENTTYPE, "image/jpeg", CURLFORM_END); string Url = "https://www.example.com/"; // 替换为真实请求地址 curl_easy_setopt(Curl, CURLOPT_URL, Url.c_str()); curl_easy_setopt(Curl, CURLOPT_HTTPHEADER, headerlist); curl_easy_setopt(Curl, CURLOPT_HTTPPOST, formpost); string Response; curl_easy_setopt(Curl, CURLOPT_WRITEFUNCTION, WriteCallback); curl_easy_setopt(Curl, CURLOPT_WRITEDATA, &Response); res = curl_easy_perform(Curl); if (res != CURLE_OK) { // 可打印curl_easy_strerror(res)查看错误原因 } curl_easy_cleanup(Curl); curl_formfree(formpost); curl_slist_free_all(headerlist); curl_global_cleanup(); return 0; }
验证说明
修复后libcurl会自动生成符合要求的multipart/form-data请求结构,不需要手动拼接任何表单相关的请求头,服务端可正常解析到name为file的文件字段,响应内容也会正常写入Response变量。
内容的提问来源于stack exchange,提问作者crow
相关产品推荐
相关产品推荐

