[英]PHP - Check if file exists on FTP server with no SIZE support
是的,我知道,很難相信這些FTP服務器仍然存在,但它們確實存在。 IBM iSeries機器運行此類服務器。
我已經得到了一個涉及ftp_nlist
和in_array
的答案但是,正如你們中的一些人可能已經猜到的那樣,當目錄包含大量項目時,這很慢 。
由於缺乏對SIZE的支持, fopen
在讀取模式下使用時總是會失敗(請記住,FTP包裝器不支持x
),而ftp_size
總是返回-1
(這是預期的)而file_exists
總是返回false
(可能是因為它內部使用SIZE?)。
ftp_get
和ftp_fget
可以解決這個問題,但是如果它存在,它們會下載整個文件。 不是很好。 一種可能的解決方案是使用ftp_fget
傳遞僅在讀取模式下打開的文件的處理程序,並捕獲引發的警告。 當文件不存在時它會有所不同,但這個解決方案感覺粗魯,我真的不知道它是否可行(也許有人可以給出一個例子)。
另一種解決方案使用ftp_nb_get
/ ftp_nb_fget
嘗試檢索文件。 如果函數返回0
( FTP_FAILED
),則該文件可能不存在。 我仍然需要處理一個臨時的本地文件,如果返回FTP_MOREDATA
(或者無法發出其他FTP命令),它很難關閉並重新打開連接。
你對此有什么想法嗎?
SIZE
命令不是必需的。 您可以簡單地使用函數ftp_nlist()
,因為FTP LIST
命令允許傳遞目錄以及文件作為參數。
雖然缺少PHP文檔,但它在RFC 959 (第32頁)中指定並且正在運行。 這是一個例子。 (謝謝Debian!
)
$server = 'ftp.us.debian.org';
$port = 21;
$user = 'anonymous';
$pwd = 'foo@bar.xxx';
$conn = ftp_connect($server);
$ret = ftp_login($conn, $user, $pwd);
foreach(array(
'debian/README.html',
'NOT_FOUND.html'
) as $file) {
$listing = ftp_nlist($conn, $file);
if(empty($listing)) {
echo "$file was not found on $server\n";
} else {
echo "$file was found on $server\n";
}
}
或者,表示為一個功能:
function ftp_file_exists(
$server,
$filename,
$user = 'anonymous' ,
$pwd = '',
$port = 21
) {
$conn = @ftp_connect($server);
if($conn === FALSE) {
die("Failed to connect to $server");
}
$ret = @ftp_login($conn, $user, $pwd);
if($ret === FALSE) {
die("Failed to login at $server");
}
$listing = @ftp_nlist($conn, $file);
if($listing === FALSE) {
die("Failed to obtain LIST response from $server");
}
return !empty($listing);
}
在評論中,討論了LIST
的結果是多么有用和可靠。 讓我說一些額外的句子......
在服務器上創建文件
請注意,您應該避免依賴以下內容:
if(file_not_exists_on_server($filename)) {
create_file_on_server($filename);
}
因為有可能該文件將由第一個和第二個函數之間的另一個客戶端創建。 雖然在本地文件系統上也是如此,但它可能更容易發生在分布式客戶端服務器應用程序中,因為與本地文件系統相比,響應時間更長,並且可能存在許多甚至是匿名客戶端(如上例所示)
在遠程創建文件時,我建議在公共可寫文件夾中遵循強大的命名方案,以避免沖突。 遵循這個方案,然后寫,不關心。 可能發生的最糟糕的事情是你覆蓋了其他人偶然創造的東西。 但誰偶然創建了像/client/id/file_name.txt
這樣的東西?
從服務器下載文件或移動,刪除服務器上的文件
嘗試其中一個操作時,在操作之前不關心文件是否存在。 去做就對了。 但如果失敗,則需要正確處理錯誤。
你可以使用某種“臟技巧” :嘗試在測試文件上做ftp_rename()
。 樣本將是:
$result = ftp_rename($connection, $testedFile, $testedFile);
如果它會失敗,那么我們很可能不存在文件。 除非您確定權限問題,否則不是100%。 但如果它會成功 - 那么文件肯定存在。 我懷疑還有另一種方法可以使用,並允許您避免文件傳輸到本地FS或處理完整目錄列表。
那么file_exists()或其他stat()系列函數呢? FTP包裝器支持它。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.