如何用curlpp实现curl的-F文件上传POST请求?
问题描述
执行以下curl命令可正常向https://somewebsite.com/发送POST请求并上传test.txt文件:
curl -F "file=@test.txt" https://somewebsite.com/
但用curlpp实现相同功能时遇到问题,当前代码如下:
#include <cstdlib> #include <cerrno> #include <iostream> #include <curlpp/cURLpp.hpp> #include <curlpp/Easy.hpp> #include <curlpp/Options.hpp> #include <curlpp/Exception.hpp> int main(int argc, char *argv[]) { if (argc < 2) { std::cerr << "Wrong number of arguments!" << std::endl << "Usage: test2 [url]" << std::endl; return EXIT_FAILURE; } char *url = argv[1]; try { curlpp::Easy request; request.setOpt(new curlpp::options::Url(url)); //request.setOpt(new curlpp::options::Verbose(true)); std::list<std::string> header; header.push_back("User-Agent: \"testing post_request\""); request.setOpt(new curlpp::options::HttpHeader(header)); std::string POSTrequest = "file=@test.txt"; request.setOpt(new curlpp::options::PostFields(POSTrequest)); request.setOpt(new curlpp::options::PostFieldSize(POSTrequest.length())); request.setOpt(new curlpp::options::WriteStream(&std::cout)); request.perform(); } catch ( curlpp::LogicError & e ) { std::cout << e.what() << std::endl; } catch ( curlpp::RuntimeError & e ) { std::cout << e.what() << std::endl; } return EXIT_SUCCESS; }
运行程序后服务器返回:
Segmentation fault (Bad request. Check POST parameters. Hint: The curl command line requires an @ before local file names.)
尝试过去掉@、拆分字段、更换分隔符、使用绝对路径等方法均无效,系统为Fedora 41。
补充说明
执行curl -F "file=@test.txt" https://somewebsite.com/ --libcurl ./test.c生成了libcurl示例代码,可见curl是通过curl_mime系列函数实现文件上传,而非普通POST。现询问如何用curlpp实现相同功能?
解决方案
curlpp对应libcurl的curl_mime功能,需要使用curlpp::Mime和curlpp::Part类构建multipart/form-data请求,替换原来的PostFields方式。修改后的代码如下:
#include <cstdlib> #include <iostream> #include <curlpp/cURLpp.hpp> #include <curlpp/Easy.hpp> #include <curlpp/Options.hpp> #include <curlpp/Mime.hpp> #include <curlpp/Exception.hpp> int main(int argc, char *argv[]) { if (argc < 2) { std::cerr << "参数错误!" << std::endl << "用法: test2 [url]" << std::endl; return EXIT_FAILURE; } try { curlpp::Easy request; // 设置请求URL request.setOpt(new curlpp::options::Url(argv[1])); // 可选:开启调试模式查看请求详情 // request.setOpt(new curlpp::options::Verbose(true)); // 设置User-Agent std::list<std::string> headers; headers.push_back("User-Agent: \"testing post_request\""); request.setOpt(new curlpp::options::HttpHeader(headers)); // 构建MIME表单 curlpp::Mime mime(request); // 添加文件字段 curlpp::Part filePart; filePart.setOpt(new curlpp::options::MimeFilename("test.txt")); filePart.setOpt(new curlpp::options::MimeName("file")); mime.addPart(filePart); // 将MIME表单绑定到请求 request.setOpt(new curlpp::options::HttpPost(mime)); // 设置响应输出流 request.setOpt(new curlpp::options::WriteStream(&std::cout)); // 执行请求 request.perform(); } catch (const curlpp::LogicError& e) { std::cerr << "逻辑错误: " << e.what() << std::endl; return EXIT_FAILURE; } catch (const curlpp::RuntimeError& e) { std::cerr << "运行时错误: " << e.what() << std::endl; return EXIT_FAILURE; } return EXIT_SUCCESS; }
关键修改点说明
- 引入
curlpp/Mime.hpp头文件,这是处理multipart/form-data请求的核心依赖 - 移除
PostFields和PostFieldSize设置,改用curlpp::Mime构建表单 - 通过
curlpp::Part创建文件字段:MimeFilename指定本地文件路径,MimeName对应表单字段名file - 用
HttpPost选项将MIME表单绑定到请求,替代普通POST的参数设置
编译时需确保链接curlpp库,示例命令:
g++ -o test2 test2.cpp -lcurlpp -lcurl
内容的提问来源于stack exchange,提问作者clouded.
相关产品推荐
相关产品推荐

