C++ cUrl 将多个/表单数据文件发送到网络服务器
C++ cUrl Send mulipart/form-data file to webserver
就像标题说我想在C++程序中发送一个带有cUrl库的文件到网络服务器。
我从服务器那里得到了网址和它想要HTTP POST方法和多部分/表单数据的信息。它还需要一个包含数据的参数文件。
我还得到了一个与 curl 控制台一起使用的 cUrl 调用:
curl -X POST -H "Cache-Control: no-cache" -H "Content-Type: multipart/form-data " -F "file=@test.txt" "url"
如果我运行下面的代码,服务器会带来没有上传或没有多部分表单的答案。
现在我的代码:
//## File stuff
struct stat file_info;
FILE *fd;
fopen_s(&fd,"file.txt", "rb"); /* open file to upload */
if (!fd) {
return 1; /* can't continue */
}
/* to get the file size */
if (fstat(_fileno(fd), &file_info) != 0) {
return 1; /* can't continue */
}
//##
CURL *hnd = curl_easy_init();
curl_easy_setopt(hnd, CURLOPT_CUSTOMREQUEST, "POST");
curl_easy_setopt(hnd, CURLOPT_URL, "url");
struct curl_slist *headers = NULL;
headers = curl_slist_append(headers, "cache-control: no-cache");
headers = curl_slist_append(headers, "content-type: multipart / form-data");
curl_easy_setopt(hnd, CURLOPT_HTTPHEADER, headers);
curl_easy_setopt(hnd, CURLOPT_UPLOAD, 1L);
curl_easy_setopt(hnd, CURLOPT_READDATA, fd);
curl_easy_setopt(hnd, CURLOPT_INFILESIZE_LARGE,(curl_off_t)file_info.st_size);
CURLcode ret = curl_easy_perform(hnd);
编辑
带有缓冲区文件的新代码:
std::string contents;
std::ifstream in("empty.txt", std::ios::in | std::ios::binary);
if (in)
{
in.seekg(0, std::ios::end);
contents.resize(in.tellg());
in.seekg(0, std::ios::beg);
in.read(&contents[0], contents.size());
in.close();
}
CURL *hnd = curl_easy_init();
uint32_t size = contents.size();
//struct curl_slist *headers = NULL;
//headers = curl_slist_append(headers, "cache-control: no-cache");
//headers = curl_slist_append(headers, "content-type: multipart/form-data");
//curl_easy_setopt(hnd, CURLOPT_HTTPHEADER, headers);
curl_easy_setopt(hnd, CURLOPT_URL, "url");
curl_easy_setopt(hnd, CURLOPT_POST, 1);
curl_easy_setopt(hnd, CURLOPT_POSTFIELDS, contents.data());
curl_easy_setopt(hnd, CURLOPT_POSTFIELDSIZE, size);
CURLcode ret = curl_easy_perform(hnd);
现在服务器响应说没有文件数据。我是否也要说它是多部分/表单数据?但是,如果我取消注释标题设置,则响应是有关多形式边界的错误。我也对想要的"file"参数感到困惑。我必须将其添加到CURLOPT_POSTFIELDS吗?
希望你们中的一个人能帮助我谢谢!
编辑最终
知道了。以下代码适用于我与给定服务器设置。
std::string contents;
std::ifstream in("file.txt", std::ios::in | std::ios::binary);
if (in)
{
in.seekg(0, std::ios::end);
contents.resize(in.tellg());
in.seekg(0, std::ios::beg);
in.read(&contents[0], contents.size());
in.close();
}
//##
CURL *curl;
CURLcode res;
struct curl_httppost *formpost = NULL;
struct curl_httppost *lastptr = NULL;
struct curl_slist *headerlist = NULL;
static const char buf[] = "Expect:";
curl_global_init(CURL_GLOBAL_ALL);
// set up the header
curl_formadd(&formpost,
&lastptr,
CURLFORM_COPYNAME, "cache-control:",
CURLFORM_COPYCONTENTS, "no-cache",
CURLFORM_END);
curl_formadd(&formpost,
&lastptr,
CURLFORM_COPYNAME, "content-type:",
CURLFORM_COPYCONTENTS, "multipart/form-data",
CURLFORM_END);
curl_formadd(&formpost, &lastptr,
CURLFORM_COPYNAME, "file", // <--- the (in this case) wanted file-Tag!
CURLFORM_BUFFER, "data",
CURLFORM_BUFFERPTR, contents.data(),
CURLFORM_BUFFERLENGTH, contents.size(),
CURLFORM_END);
curl = curl_easy_init();
headerlist = curl_slist_append(headerlist, buf);
if (curl) {
curl_easy_setopt(curl, CURLOPT_URL, "url");
curl_easy_setopt(curl, CURLOPT_HTTPPOST, formpost);
//curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, WriteCallback);
//curl_easy_setopt(curl, CURLOPT_WRITEDATA, &readBuffer);
//curl_easy_setopt(curl, CURLOPT_VERBOSE, 1L);
res = curl_easy_perform(curl);
/* Check for errors */
if (res != CURLE_OK)
fprintf(stderr, "curl_easy_perform() failed: %sn",
curl_easy_strerror(res));
curl_easy_cleanup(curl);
curl_formfree(formpost);
curl_slist_free_all(headerlist);
}
您没有正确设置多部分数据的格式。您可以在netcat
实用程序的帮助下看到它应该是什么样子:
在 1 号航站楼:
$ nc -lk 8080 # listen for TCP connection on port 8080
在 2 号航站楼:
$ curl -X POST -F "file=@test.txt" localhost:8080
通过检查终端 1,您将看到 curl 发送了类似于以下内容的请求:
POST / HTTP/1.1
Host: localhost:8080
User-Agent: curl/7.43.0
Accept: */*
Content-Length: 193
Expect: 100-continue
Content-Type: multipart/form-data; boundary=------------------------a975b09b8e15800c
--------------------------a975b09b8e15800c
Content-Disposition: form-data; name="file"; filename="test.txt"
Content-Type: text/plain
qwerty
--------------------------a975b09b8e15800c--
现在,通过将数据发送到netcat(localhost:8080)来调试C++代码并修复代码,直到其请求类似于curl发送的请求。
一般建议 - 不要盲目调试。您无法控制的服务器的响应无法提供有关问题的足够信息。如果可能,请在允许您查看数据的每一位并验证数据是否符合规范和/或您的期望的环境中进行调试。
您的命令行正在使用 POST
,但您的代码使用的是 CURLOPT_UPLOAD
,这显然是不同的。
您应该改用CURLOPT_POST
,并且应该将文件读取(或映射)到缓冲区中:
// Assume you read or map your file into
// `uint8_t* buffer`, with `uint32_t size`
...
CURL *hnd = curl_easy_init();
curl_easy_setopt(hnd, CURLOPT_URL, "url");
curl_easy_setopt(hnd, CURLOPT_POST, 1);
curl_easy_setopt(hnd, CURLOPT_POSTFIELDS, buffer);
curl_easy_setopt(hnd, CURLOPT_POSTFIELDSIZE, size);
- 如何结束异步网络服务器 ESP32.
- 用于本地网络运行的客户端服务器体系结构
- 如何使用标准库网络 TS 在服务器和客户端之间发送消息C++
- 将 URL/href 从网络服务器重新派生到ESP8266(以处理它)
- 自动启动网络服务器和程序
- 是否可以寻址另一个网络中的服务器/客户端套接字?(C++)
- 你好世界示例,一个在 C 语言中使用 SSL 的猫鼬网络服务器
- ESP8266网络服务器如何流式传输未签名的字符
- 使用WordPress在网络服务器上运行C 应用程序
- 使用Boost.ASIO与服务器进行简单的网络tcp通信
- 如何制作安卓网络服务器
- C++ REST SDK http_listener作为网络服务器
- SFML网络服务器/客户端
- 使用 Poco 将图像发送到网络服务器
- C++在 Windows 服务器 2008 r2 中禁用网络适配器的示例
- 损坏的HTML - 浏览器不会从我的网络服务器下载整个HTTP响应,CURL可以
- 猫鼬网络服务器获取当前工作线程
- 用c++创建高性能网络服务器
- C++ cUrl 将多个/表单数据文件发送到网络服务器
- 网络服务器的编程语言