【问题标题】:using libcurl to check if a file exists on a SFTP site使用 libcurl 检查 SFTP 站点上是否存在文件
【发布时间】:2010-03-19 14:15:30
【问题描述】:

我使用 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,我可以使用它。

【问题讨论】:

  • 你解决过这个问题吗?我也有同样的问题。

标签: c++ ftp curl sftp libcurl


【解决方案1】:

在 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

但是,SFTP 的 CURLOPT_NOBODY 和 CURLOPT_HEADER 不会返回错误 如果文件在某些​​以前版本的 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

【讨论】:

  • 为什么要 10 个字节而不是 1 个字节?
  • @RemyLebeau:这无关紧要。目的是只下载尽可能多的文件以了解文件是否存在。网络上的 1 个字节或 10 个字节实际上没有任何区别。
  • @RemyLebeau:确实,目前形式的替代解决方案存在缺陷。如果它是一个 0 字节的远程文件,则返回的错误是 CURLE_BAD_DOWNLOAD_RESUME,因为指定的偏移量大于预期的大小。编辑我的答案。
【解决方案2】:

我找到了一种方法来完成这项工作。基本概念是尝试读取文件,如果文件存在则中止读取操作,以避免下载整个文件。所以它要么从 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);

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2012-06-13
    • 2011-03-06
    • 2015-12-14
    • 2012-11-09
    • 1970-01-01
    • 2020-12-20
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多