gpt4 book ai didi

C++ cUrl 将多部分/表单数据文件发送到 Web 服务器

转载 作者:塔克拉玛干 更新时间:2023-11-03 00:47:01 28 4
gpt4 key购买 nike

就像标题说的那样,我想在 C++ 程序中将带有 cUrl 库的文件发送到网络服务器。

我从服务器获得了 url 以及它需要 HTTP POST 方法和 mutipart/form-data 的信息。它还需要一个包含数据的参数文件。

我还有一个与 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: %s\n",
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 发送的请求。

一般性建议 - 不要盲目调试。您无法控制的服务器的响应没有提供足够的问题信息。如果可能,请在允许您查看数据的每一位并验证数据是否符合规范和/或您的期望的环境中进行调试。

关于C++ cUrl 将多部分/表单数据文件发送到 Web 服务器,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/38320819/

28 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com