I am trying to upload a file to a webserver using libcurl (in C). The server requires that I use POST, not PUT (which is what CURLOPT_UPLOAD would use). I also need to send a specific token in the header. This is what I have so far:
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;
}
The only response I get from the server is that it is a "400 Bad Request".
I have written code in Python that performs the same action, and this file upload works:
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())
UPDATE: After running with verbose mode:
> 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
....
I think you're missing a call just before the curl_easy_perform()
that is,
curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers);
Also, add
curl_easy_setopt(curl, CURLOPT_VERBOSE 1L);
to get verbose output, it can be very useful in debugging, and would likely have made your above missing headers obvious.
Edit:
You need to set the post field size CURLOPT_POSTFIELDSIZE
and may need to clear the Expect:
header as well.
curl_easy_setopt(curl, CURLOPT_POSTFIELDSIZE, file_info.st_size);
....
headers = curl_slist_append(headers, "Expect:");
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With