我想让HTTPS PUT请求放一个csv文件。下面是用于将数据上传到Xively的代码。早些时候我得到411长度要求的错误。我提到了这里可用的代码(Send string in PUT request with libcurl)来解决这个问题,其中进行了CURLOPT_CUSTOMREQUEST。现在我收到HTTP 500内部服务器错误。
void upload()
{
CURL *curl;
CURLcode res;
FILE * hd_src;
struct stat file_info;
struct curl_slist* header = NULL;
char * csvfile = "123.csv";
/* get the file size */
stat(csvfile, &file_info);
hd_src = fopen("123.csv","rb");
curl_global_init(CURL_GLOBAL_ALL);
curl = curl_easy_init();
if(curl)
{
header = curl_slist_append(header,"X-ApiKey: 123123123"); /* API KEY HERE - sample only*/
header = curl_slist_append(header,"Accept: text/csv");
header = curl_slist_append(header, "Host: api.xively.com");
curl_easy_setopt(curl, CURLOPT_HTTPHEADER, header);
curl_easy_setopt(curl, CURLOPT_VERBOSE, 1L);
/* Actual Xively feed is here. For demonstration purpose the feed is listed as 123 */
curl_easy_setopt(curl, CURLOPT_URL, "https://api.xively.com/v2/feeds/123.csv");
curl_easy_setopt(curl, CURLOPT_READDATA, hd_src);
curl_easy_setopt(curl, CURLOPT_INFILESIZE_LARGE, (curl_off_t)file_info.st_size);
curl_easy_setopt(curl, CURLOPT_CUSTOMREQUEST, "PUT" );
curl_easy_setopt(curl, CURLOPT_POSTFIELDS, hd_src);
res = curl_easy_perform(curl);
if(res != CURLE_OK)
{
fprintf(stderr, "curl_easy_perform() failed: %s\n", curl_easy_strerror(res));
}
curl_easy_cleanup(curl);
}
fclose(hd_src);
curl_slist_free_all(header);
curl_global_cleanup();
}
有人可以提出建议吗?如果我删除curl_easy_setopt(curl,CURLOPT_POSTFIELDS,hd_src),我将得到411长度所需的错误。我删除了这个并使用file_info.st_size将Content-Length添加到标头中。再次收到411长度要求的错误。使用curl_easy_setopt(curl,CURLOPT_POSTFIELDS,hd_src)411已解决,但Xively提供500内部服务器错误。
提前致谢。
答案 0 :(得分:1)
请尝试使用CURLOPT_UPLOAD
,例如documentation说:
CURLOPT_PUT - 发出HTTP PUT请求
...
自版本7.12.1起不推荐使用此选项。使用CURLOPT_UPLOAD!
CURLOPT_UPLOAD - 启用数据上传
...
如果协议是HTTP,则上传意味着使用PUT请求,除非您告诉libcurl
你必须非常小心CURLOPT_CUSTOMREQUEST
:
CURLOPT_CUSTOMREQUEST - 请求的自定义字符串
...
当您通过将CURLOPT_CUSTOMREQUEST设置为某个更改请求方法时,您实际上并未更改libcurl对特定请求方法的行为或行为方式,它只会更改请求中发送的实际字符串
...
许多人错误地使用此选项用自己的请求替换整个请求,包括多个标头和POST内容。虽然在许多情况下这可能会起作用,但它会导致libcurl发送无效请求,并且可能会严重混淆远程服务器。
您也没有发送Content-Type
标头,而是发送Accept
标头。 Content-Type
告诉服务器您要发送的数据类型。 Accept
告诉服务器您愿意收到哪些类型的数据。
最后,您没有在stat()
或fopen()
上进行错误处理。
请改为尝试:
void upload()
{
CURL *curl;
CURLcode res;
FILE * hd_src;
struct stat file_info = {0};
struct curl_slist* header = NULL;
char * csvfile = "C:\\full path to\\123.csv";
/* get the file size */
if (stat(csvfile, &file_info) == -1)
{
fprintf(stderr, "stat() failed: %s\n", strerror(errno));
return;
}
hd_src = fopen(csvfile, "rb");
if (!hd_src)
{
fprintf(stderr, "fopen() failed: %s\n", strerror(errno));
return;
}
curl_global_init(CURL_GLOBAL_ALL);
curl = curl_easy_init();
if (!curl)
{
fprintf(stderr, "curl_easy_init() failed\n");
}
else
{
header = curl_slist_append(header, "X-ApiKey: 123123123"); /* API KEY HERE - sample only*/
header = curl_slist_append(header, "Content-Type: text/csv");
curl_easy_setopt(curl, CURLOPT_HTTPHEADER, header);
curl_easy_setopt(curl, CURLOPT_VERBOSE, 1L);
/* Actual Xively feed is here. For demonstration purpose the feed is listed as 123 */
curl_easy_setopt(curl, CURLOPT_URL, "https://api.xively.com/v2/feeds/123.csv");
curl_easy_setopt(curl, CURLOPT_READDATA, hd_src);
curl_easy_setopt(curl, CURLOPT_INFILESIZE_LARGE, (curl_off_t)file_info.st_size);
curl_easy_setopt(curl, CURLOPT_UPLOAD, 1L );
res = curl_easy_perform(curl);
if (res != CURLE_OK)
fprintf(stderr, "curl_easy_perform() failed: %s\n", curl_easy_strerror(res));
curl_slist_free_all(header);
curl_easy_cleanup(curl);
}
fclose(hd_src);
curl_global_cleanup();
}