2010-03-19 112 views
3

我正在使用C++和libcurl來執行SFTP/FTPS傳輸。在上傳文件之前,我需要檢查文件是否存在,而不是實際下載文件。使用libcurl檢查SFTP站點上是否存在文件

如果文件不存在,我遇到了以下問題:

//set up curlhandle for the public/private keys and whatever else first. 
curl_easy_setopt(CurlHandle, CURLOPT_URL, "sftp://[email protected]: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,我可以使用它。

+0

您是否曾經解決過這個問題?我有同樣的問題。 – Lextar 2011-02-10 19:47:13

回答

0

我找到了一種方法來完成這項工作。基本概念是嘗試讀取文件,然後在文件存在的情況下中止讀取操作,以避免下載整個文件。因此,它會無論是從捲曲得到一個返回的錯誤「文件不存在」或「錯誤寫入數據」:

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); 
2

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而對於SFTP,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 
+0

爲什麼要求10個字節而不是1個字節? – 2015-05-21 18:13:17

+0

@RemyLebeau:那不重要。目的是隻下載儘可能多的文件以知道文件是否存在。通過網絡1個字節或10個字節實際上沒有任何區別。 – 2015-05-21 18:16:19

+0

@RemyLebeau:事實上,目前形式的替代解決方案存在缺陷。如果它是一個0字節的遠程文件,則返回的錯誤是CURLE_BAD_DOWNLOAD_RESUME,因爲指定的偏移量大於預期的大小。編輯我的答案。 – 2015-05-23 08:20:13