Как отправить длинные данные PUT в libcurl без использования файловых указателей? - PullRequest
3 голосов
/ 25 августа 2010

Я пытаюсь взаимодействовать с Google Contact API, и для обновления контакта на удаленной стороне мне нужно использовать запрос PUT вместо POST.

Поскольку данные, которые я хочу PUT, уже находятся в памяти, я действительно не хочу иметь дело с файловыми указателями, что, по-видимому, является поведением по умолчанию CURLOPT_READDATA. Таким образом, я понимаю, что мне нужно использовать CURLOPT_READFUNCTION в дополнение к этому, но я не понимаю логику.

Вот соответствующий документ: http://curl.haxx.se/libcurl/c/curl_easy_setopt.html#CURLOPTREADFUNCTION

При печати переданных переменных я вижу nmemb=16372 и size=1. Например, если мои данные будут иметь размер 100 КБ, какую логику мне необходимо реализовать?

Спасибо.

Ответы [ 2 ]

7 голосов
/ 25 августа 2010

Вы по-прежнему хотите использовать CURLOPT_READDATA, однако, если вы используете CURLOPT_READFUNCTION, это может быть любой указанный пользователем указатель. Вы можете создать простую структуру, такую ​​как:

struct put_data
{
  char *data;
  size_t len;
};

, где data - данные PUT, а len - длина (оставшаяся).

Затем установите CURLOPT_READDATA на указатель на инициализированный экземпляр этой структуры. Вы получите его в CURLOPT_READFUNCTION как userdata. В этой функции сделайте что-то вроде:

size_t curl_size = nmemb * size;
size_t to_copy = (userdata->len < curl_size) ? userdata->len : curl_size;
memcpy(ptr, userdata->data, to_copy);
userdata->len -= to_copy;
userdata->data += to_copy;
return to_copy;

Это в основном вычисляет сумму для копирования, копирует ее, затем обновляет длину и указатель. В строке to_copy мы вычисляем минимум, поскольку он ограничен как оставшимся количеством, так и размером буфера curl. Наконец, мы возвращаем количество скопированных байтов, как того требует curl. Когда вы в конце содержимого user_data->len (и, следовательно, to_copy) будет равно 0. Ничего не будет скопировано, и возврат 0 завершит передачу.

1 голос
/ 21 января 2015

ЭТО правильный способ сделать это.

Еще одна вещь, которую нужно иметь в виду, это то, что вы ДОЛЖНЫ установить РАЗМЕР ФАЙЛА:

curl_easy_setopt(curlHandle, CURLOPT_INFILESIZE,(curl_off_t)putData.size);

В противном случае ваш сервер может выдать ошибку о том, что длина запроса не указана.

putData является экземпляром структуры put_data.

...