在 C++ 中使用 libcurl 通过多部分发送文件
Sending a file via multipart using libcurl in C++
我正在尝试使用 libcurl 和 C++ 通过 POST 请求将文件上传到远程位置。但是,我认为我做错了什么,因为我被告知文件没有到达另一端。
我正在使用以下代码:
#include "curl/curl.h"
using namespace std;
size_t WriteCallback(void * buffer, size_t size, size_t count, void * user)
{
((string *) user)->append((char *) buffer, 0, size * count);
return size * count;
}
int main()
{
curl_global_init(CURL_GLOBAL_ALL);
CURL * Curl;
CURLCode res;
Curl = curl_easy_init();
curl_easy_setopt(Curl, CURLOPT_FAILONERROR, 0);
curl_easy_setopt(Curl, CURLOPT_VERBOSE, 1L);
struct curl_httppost * formpost = NULL;
struct curl_httppost * lastptr = NULL;
struct curl_slist * headerlist = NULL;
static const char buf[] = "Expect:";
ImageName = "myimage.jpg"
ImageNameWithPath = "/this/location/right/here/" + ImageName;
curl_formadd(& formpost,
& lastptr,
CURLFORM_COPYNAME, ImageName.c_str();
CURLFORM_FILE, ImageNameWithPath.c_str();
CURLFORM_CONTENTTYPE, "image/jpeg (binary)";
CURLFORM_END);
curl_formadd(& formpost,
& lastptr,
CURLFORM_COPYNAME, ImageName.c_str();
CURLFORM_COPYCONTENTS, ImageNameWithPath.c_str();
CURLFORM_CONTENTTYPE, "image/jpeg (binary)";
CURLFORM_END);
headerlist = curl_slist_append(headerlist, buf);
string MessageBodyLine1 = "Content-Disposition: form-data; name=\"file\"; filename\"" + ImageName + "\"";
headerlist = curl_slist_append(headerlist, MessageBodyLine1.c_str());
string Url = https://www.example.com/ // There is a real URL here
curl_easy_setopt(Curl, CURLOPT_URL, Ulr.c_str());
curl_easy_setopt(Curl, CURLOPT_HTTPHEADER, headerlist);
curl_easy_setopt(Curl, CURLOPT_HTTPPOST, formpost);
string Reponse;
curl_easy_setopt(Curl, CURLOPT_WRITEFUNCTION, WriteCallback);
curl_easy_setopt(Curl, CURLOPT_WRITEDATA, & Response);
res = curl_easy_perform(Curl);
curl_easy_cleanup(Curl);
curl_formfree(formpost);
curl_slist_free_all(headerlist);
curl_global_cleanup();
return 0;
我实际上希望某处的输出看起来像这样
POST URL HTTP/1.1
Content-Type: multipart/form-data; boundary=----BoundaryString
----BoundaryString
Content-Disposition: form-data; name="file"; filename="myfile.jpg"
Content-Type: image/jpeg (binary)
相反,我得到了这个:
* Trying IP
* Connected to IP port PORT (#0)
POST URL HTTP/1.1
Host: IP
Accept: IP:PORT
Content-Disposition: form-data; name="file"; filename="myfile.jpg"
Content-Length: totalsize
Content-Type: multipart/form-data; boundary=----BoundaryString
< HTTP/1.1 200 OK
[...]
现在它说好的,但我知道图像没有到达另一边。此外,我的 Response
字符串也是空的,而它应该包含一个 JSON 字符串。
我做错了什么?不幸的是,我坚持使用较旧的 libcurl 版本,因此无法使用 curl 7.55 中可用的 mime 格式。
不要在 HTTP 请求的 headerlist
中添加 Content-Disposition
请求 header,它不属于那里。它属于每个 MIME 部分(即,您应该使用 CURLFORM_COPYNAME, "file"
和 CURLFORM_FILE, ImageName.c_str()
)。我希望 curl_formadd()
为您处理 Content-Disposition
,您不需要手动创建它。
此外,image/jpeg (binary)
不是有效的 Content-Type
值,它只需要 image/jpeg
.
你为什么要为同一个文件两次调用 curl_formadd()
,一次调用 CURLFORM_FILE
,另一次调用 CURLFORM_COPYCONTENTS
?特别是因为您对 CURLFORM_COPYCONTENTS
的输入是错误的(它需要指向实际数据的指针,而不是指向文件名字符串的指针)。在这种情况下,您应该只使用 CURLFORM_FILE
。
试试这个:
#include "curl/curl.h"
#include <string>
using namespace std;
size_t WriteCallback(void * buffer, size_t size, size_t count, void * user)
{
size_t numBytes = size * count;
static_cast<string*>(user)->append(static_cast<char*>(buffer), 0, numBytes);
return numBytes;
}
int main()
{
curl_global_init(CURL_GLOBAL_ALL);
CURL *Curl = curl_easy_init();
if (!Curl)
return -1;
curl_easy_setopt(Curl, CURLOPT_FAILONERROR, 0);
curl_easy_setopt(Curl, CURLOPT_VERBOSE, 1L);
curl_httppost *formpost = NULL;
curl_httppost *lastptr = NULL;
string ImageName = "myimage.jpg";
string ImageNameWithPath = "/this/location/right/here/" + ImageName;
curl_formadd(&formpost,
&lastptr,
CURLFORM_COPYNAME, "file",
CURLFORM_FILE, ImageNameWithPath.c_str(),
CURLFORM_CONTENTTYPE, "image/jpeg",
CURLFORM_END);
curl_slist *headerlist = curl_slist_append(NULL, "Expect:");
string Url = https://www.example.com/ // There is a real URL here
curl_easy_setopt(Curl, CURLOPT_URL, Url.c_str());
curl_easy_setopt(Curl, CURLOPT_HTTPHEADER, headerlist);
curl_easy_setopt(Curl, CURLOPT_HTTPPOST, formpost);
string Reponse;
curl_easy_setopt(Curl, CURLOPT_WRITEFUNCTION, WriteCallback);
curl_easy_setopt(Curl, CURLOPT_WRITEDATA, &Response);
CURLCode res = curl_easy_perform(Curl);
curl_easy_cleanup(Curl);
curl_formfree(formpost);
curl_slist_free_all(headerlist);
curl_global_cleanup();
return 0;
}
我正在尝试使用 libcurl 和 C++ 通过 POST 请求将文件上传到远程位置。但是,我认为我做错了什么,因为我被告知文件没有到达另一端。
我正在使用以下代码:
#include "curl/curl.h"
using namespace std;
size_t WriteCallback(void * buffer, size_t size, size_t count, void * user)
{
((string *) user)->append((char *) buffer, 0, size * count);
return size * count;
}
int main()
{
curl_global_init(CURL_GLOBAL_ALL);
CURL * Curl;
CURLCode res;
Curl = curl_easy_init();
curl_easy_setopt(Curl, CURLOPT_FAILONERROR, 0);
curl_easy_setopt(Curl, CURLOPT_VERBOSE, 1L);
struct curl_httppost * formpost = NULL;
struct curl_httppost * lastptr = NULL;
struct curl_slist * headerlist = NULL;
static const char buf[] = "Expect:";
ImageName = "myimage.jpg"
ImageNameWithPath = "/this/location/right/here/" + ImageName;
curl_formadd(& formpost,
& lastptr,
CURLFORM_COPYNAME, ImageName.c_str();
CURLFORM_FILE, ImageNameWithPath.c_str();
CURLFORM_CONTENTTYPE, "image/jpeg (binary)";
CURLFORM_END);
curl_formadd(& formpost,
& lastptr,
CURLFORM_COPYNAME, ImageName.c_str();
CURLFORM_COPYCONTENTS, ImageNameWithPath.c_str();
CURLFORM_CONTENTTYPE, "image/jpeg (binary)";
CURLFORM_END);
headerlist = curl_slist_append(headerlist, buf);
string MessageBodyLine1 = "Content-Disposition: form-data; name=\"file\"; filename\"" + ImageName + "\"";
headerlist = curl_slist_append(headerlist, MessageBodyLine1.c_str());
string Url = https://www.example.com/ // There is a real URL here
curl_easy_setopt(Curl, CURLOPT_URL, Ulr.c_str());
curl_easy_setopt(Curl, CURLOPT_HTTPHEADER, headerlist);
curl_easy_setopt(Curl, CURLOPT_HTTPPOST, formpost);
string Reponse;
curl_easy_setopt(Curl, CURLOPT_WRITEFUNCTION, WriteCallback);
curl_easy_setopt(Curl, CURLOPT_WRITEDATA, & Response);
res = curl_easy_perform(Curl);
curl_easy_cleanup(Curl);
curl_formfree(formpost);
curl_slist_free_all(headerlist);
curl_global_cleanup();
return 0;
我实际上希望某处的输出看起来像这样
POST URL HTTP/1.1
Content-Type: multipart/form-data; boundary=----BoundaryString
----BoundaryString
Content-Disposition: form-data; name="file"; filename="myfile.jpg"
Content-Type: image/jpeg (binary)
相反,我得到了这个:
* Trying IP
* Connected to IP port PORT (#0)
POST URL HTTP/1.1
Host: IP
Accept: IP:PORT
Content-Disposition: form-data; name="file"; filename="myfile.jpg"
Content-Length: totalsize
Content-Type: multipart/form-data; boundary=----BoundaryString
< HTTP/1.1 200 OK
[...]
现在它说好的,但我知道图像没有到达另一边。此外,我的 Response
字符串也是空的,而它应该包含一个 JSON 字符串。
我做错了什么?不幸的是,我坚持使用较旧的 libcurl 版本,因此无法使用 curl 7.55 中可用的 mime 格式。
不要在 HTTP 请求的 headerlist
中添加 Content-Disposition
请求 header,它不属于那里。它属于每个 MIME 部分(即,您应该使用 CURLFORM_COPYNAME, "file"
和 CURLFORM_FILE, ImageName.c_str()
)。我希望 curl_formadd()
为您处理 Content-Disposition
,您不需要手动创建它。
此外,image/jpeg (binary)
不是有效的 Content-Type
值,它只需要 image/jpeg
.
你为什么要为同一个文件两次调用 curl_formadd()
,一次调用 CURLFORM_FILE
,另一次调用 CURLFORM_COPYCONTENTS
?特别是因为您对 CURLFORM_COPYCONTENTS
的输入是错误的(它需要指向实际数据的指针,而不是指向文件名字符串的指针)。在这种情况下,您应该只使用 CURLFORM_FILE
。
试试这个:
#include "curl/curl.h"
#include <string>
using namespace std;
size_t WriteCallback(void * buffer, size_t size, size_t count, void * user)
{
size_t numBytes = size * count;
static_cast<string*>(user)->append(static_cast<char*>(buffer), 0, numBytes);
return numBytes;
}
int main()
{
curl_global_init(CURL_GLOBAL_ALL);
CURL *Curl = curl_easy_init();
if (!Curl)
return -1;
curl_easy_setopt(Curl, CURLOPT_FAILONERROR, 0);
curl_easy_setopt(Curl, CURLOPT_VERBOSE, 1L);
curl_httppost *formpost = NULL;
curl_httppost *lastptr = NULL;
string ImageName = "myimage.jpg";
string ImageNameWithPath = "/this/location/right/here/" + ImageName;
curl_formadd(&formpost,
&lastptr,
CURLFORM_COPYNAME, "file",
CURLFORM_FILE, ImageNameWithPath.c_str(),
CURLFORM_CONTENTTYPE, "image/jpeg",
CURLFORM_END);
curl_slist *headerlist = curl_slist_append(NULL, "Expect:");
string Url = https://www.example.com/ // There is a real URL here
curl_easy_setopt(Curl, CURLOPT_URL, Url.c_str());
curl_easy_setopt(Curl, CURLOPT_HTTPHEADER, headerlist);
curl_easy_setopt(Curl, CURLOPT_HTTPPOST, formpost);
string Reponse;
curl_easy_setopt(Curl, CURLOPT_WRITEFUNCTION, WriteCallback);
curl_easy_setopt(Curl, CURLOPT_WRITEDATA, &Response);
CURLCode res = curl_easy_perform(Curl);
curl_easy_cleanup(Curl);
curl_formfree(formpost);
curl_slist_free_all(headerlist);
curl_global_cleanup();
return 0;
}