我试图通过POST请求上传到远程位置使用libcurl和c++。然而,我认为我做错了什么,因为我被告知文件没有到达另一边。
我使用以下代码:
#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
[...]
现在它说OK,但我知道一个事实,图像没有到达另一边。此外,我的Response
字符串也是空的,而它应该包含一个JSON字符串。
我做错了什么?不幸的是,我被一个旧的libcurl版本卡住了,因此不能使用curl 7.55中提供的mime格式。
不要在HTTP请求的headerlist
中添加Content-Disposition
请求头,它不属于那里。它属于每个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;
}