使用libcurl + POST和标题上传文件

时间:2013-11-12 22:47:45

标签: c curl libcurl

我正在尝试使用libcurl(在C中)将文件上传到网络服务器。服务器要求我使用POST,而不是PUT(这是CURLOPT_UPLOAD将使用的)。我还需要在标题中发送一个特定的标记。这就是我到目前为止所做的:

int upload(char *filepath, char *filename, char *token) {
    CURL *curl;
    CURLcode res;

    FILE *fd;
    struct stat file_info;

    char *file;
    asprintf(&file, "%s/%s", filepath, filename);

    fd = fopen(file, "rb");
    if (!fd) {
        fprintf(stderr, "Could not open file.\n");
        return 1;
    }

    if (fstat(fileno(fd), &file_info) != 0) {
        fprintf(stderr, "Could not get file information.\n");
        return 1;
    }

    curl = curl_easy_init()
    curl_easy_setopt(curl, CURLOPT_URL, "https://127.0.0.1/upload");
    curl_easy_setopt(curl, CURLOPT_READDATA, fd);
    curl_easy_setopt(curl, CURLOPT_POST, 1L);

    struct curl_slist *headers = NULL;
    headers = curl_slist_append(headers, "Content-Type:application/octet-stream");

    char *my_token = malloc(snprintf(NULL, 0, "X-Token:%s", token) + 1);
    sprintf(my_token, "X-Token:%s", token);
    headers = curl_slist_append(headers, my_token);
    curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers);
    curl_easy_setopt(curl, CURLOPT_VERBOSE, 1L);
    res = curl_easy_perform(curl);

    if (res != CURLE_OK) {
        fprintf(stderr, "curl_easy_perform() failed: %s\n", curl_easy_strerror(res));
        return 1;
    }

    fprintf(stdout, "Upload OK.\n");
    return 0;
}    

我从服务器得到的唯一回应是它是“400 Bad Request”。

我在Python中编写了执行相同操作的代码,并且此文件上载有效:

import urllib, urllib2, json, os
def upload(self, filepath, filename, token):
    # Open file
    f = open(os.path.join(filepath, filename), 'rb')
    filedata = f.read()
    f.close()

    request = urllib2.Request("https://127.0.0.1/upload" % filedata, {"Content-Type":"application/octet-stream", "X-Token":token})
    res = self.opener.open(request)
    return json.loads(res.read())

更新: 以详细模式运行后:

> POST /upload HTTP/1.1
Host: 127.0.0.1
Accept: */*
Content-Type:application/octet-stream
X-Token: 17f684-b98c
Content-Length: -1
Expect: 100-continue

< HTTP/1.1 Bad Request
....

1 个答案:

答案 0 :(得分:5)

我认为你错过了curl_easy_perform()之前的电话,

curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers);

另外,添加

curl_easy_setopt(curl, CURLOPT_VERBOSE 1L);

要获得详细的输出,它在调试时非常有用,并且可能会使上面缺少的标题变得明显。

编辑: 您需要设置帖子字段大小CURLOPT_POSTFIELDSIZE,也可能需要清除Expect:标题。

curl_easy_setopt(curl, CURLOPT_POSTFIELDSIZE, file_info.st_size);
....
headers = curl_slist_append(headers, "Expect:");