正如标题所说,我想在C++程序中使用cUrl库将文件发送到Web服务器。
我从服务器获取了URL和它需要HTTP POST方法以及mutipart/form-data的信息。此外,它还需要一个名为file的参数来传递数据。
我也有一个可以在curl控制台中使用的cUrl调用:
curl -X POST -H "Cache-Control: no-cache" -H "Content-Type: multipart/form-data " -F "file=@test.txt" "url"
如果我运行下面的代码,服务器会返回没有上传或没有multipart表单的答案。
现在是我的代码:
//## 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);
现在服务器响应没有文件数据。我是否还需要说明它是multipart/form-data?但是,如果我取消注释标题设置,响应会提示关于多行表单的错误。
另外,我对所需的“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);
}