использование libcurl для проверки наличия файла на SFTP-сайте - PullRequest
3 голосов
/ 19 марта 2010

Я использую C ++ с libcurl для передачи SFTP / FTPS. Перед загрузкой файла мне нужно проверить, существует ли файл без его фактической загрузки.

Если файл не существует, я сталкиваюсь со следующими проблемами:

//set up curlhandle for the public/private keys and whatever else first.
curl_easy_setopt(CurlHandle, CURLOPT_URL, "sftp://user@pass:host/nonexistent-file");
curl_easy_setopt(CurlHandle, CURLOPT_NOBODY, 1);
curl_easy_setopt(CurlHandle, CURLOPT_FILETIME, 1);
int result = curl_easy_perform(CurlHandle); 
//result is CURLE_OK, not CURLE_REMOTE_FILE_NOT_FOUND
//using curl_easy_getinfo to get the file time will return -1 for filetime, regardless
//if the file is there or not.

Если я не использую CURLOPT_NOBODY, это работает, я получаю CURLE_REMOTE_FILE_NOT_FOUND.

Однако, если файл существует, он загружается, что тратит впустую время для меня, так как я просто хочу знать, есть ли он там или нет.

Какие-нибудь другие методы / опции мне не хватает? Обратите внимание, что это должно работать и для ftps.


Редактировать: эта ошибка возникает с sftp. С FTPS / FTP я получаю CURLE_FTP_COULDNT_RETR_FILE, с которым я могу работать.

Ответы [ 2 ]

2 голосов
/ 21 мая 2015

Проверено это в libcurl 7.38.0

curl_easy_setopt(curl, CURLOPT_NOBODY, 1L);
curl_easy_setopt(curl, CURLOPT_HEADER, 1L);

CURLcode iRc = curl_easy_perform(curl);

if (iRc == CURLE_REMOTE_FILE_NOT_FOUND)
  // File doesn't exist
else if (iRc == CURLE_OK)
  // File exists

Однако CURLOPT_NOBODY и CURLOPT_HEADER для SFTP не возвращают ошибку если файл не существует в некоторых предыдущих версиях libcurl. Альтернативное решение для решения этой проблемы:

// Ask for the first byte
curl_easy_setopt(curl, CURLOPT_RANGE,
    (const char *)"0-0");

CURLcode iRc = curl_easy_perform(curl);

if (iRc == CURLE_REMOTE_FILE_NOT_FOUND)
  // File doesn't exist
else if (iRc == CURLE_OK || iRc == CURLE_BAD_DOWNLOAD_RESUME)
  // File exists
0 голосов
/ 20 января 2014

Я нашел способ заставить эту работу. Основная идея - попытаться прочитать файл, а затем прервать операцию чтения, если файл существует, чтобы избежать загрузки всего файла. Поэтому он либо получит возвращаемую ошибку от cURL для «файл не существует», либо «ошибка записи данных»:

static size_t abort_read(void *ptr, size_t size, size_t nmemb, void *data)
{
  (void)ptr;
  (void)data;
  /* we are not interested in the data itself,
     so we abort operation ... */ 
  return (size_t)(-1); // produces CURLE_WRITE_ERROR
}
....
curl_easy_setopt(curl,CURLOPT_URL, url);
curl_easy_setopt(curl, CURLOPT_VERBOSE, 1L);
curl_easy_setopt(curl, CURLOPT_WRITEDATA, NULL);
curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, abort_read);
CURLcode res = curl_easy_perform(curl);
/* restore options */
curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, NULL);
curl_easy_setopt(curl, CURLOPT_WRITEDATA, NULL);
curl_easy_setopt(curl, CURLOPT_URL, NULL);
return (res==CURLE_WRITE_ERROR);
...