PHP - 检查FTP服务器上是否存在没有SIZE支持的文件

时间:2014-02-26 11:56:14

标签: php ftp

是的,我知道,很难相信这些FTP服务器仍然存在,但它们确实存在。 IBM iSeries机器运行这样的服务器。

我已经得到了一个涉及ftp_nlistin_array的答案,但是,正如你们中的一些人可能已经猜到的那样,当目录包含大量数字时,这是物品。

由于缺少对SIZE的支持,fopen在读取模式下使用时总是失败(请记住,FTP包装器不支持x),而ftp_size总是返回-1(预期)和file_exists始终返回false(也许是因为它在内部使用了SIZE?)。

  • ftp_getftp_fget可以解决问题,但如果存在则会下载整个文件。不是很好。一种可能的解决方案是使用ftp_fget传递仅在读取模式下打开的文件的处理程序,并捕获引发的警告。当文件不存在时会有所不同,但这个解决方案感觉粗鲁,我真的不知道它是否可行(也许有人可以给出一个例子)。

  • 另一种解决方案使用ftp_nb_get / ftp_nb_fget来尝试检索文件。如果函数返回0FTP_FAILED),则该文件可能不存在。我仍然需要处理一个临时的本地文件,如果返回FTP_MOREDATA(或者无法发出其他FTP命令),它很难关闭并重新打开连接。

你对此有什么想法吗?

3 个答案:

答案 0 :(得分:4)

不需要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之类的东西?


从服务器下载文件或移动,删除服务器上的文件

尝试其中一项操作时,无需关心操作前文件是否存在。去做就对了。但是如果它失败了,你需要正确处理错误。

答案 1 :(得分:2)

您可以使用某种“脏技巧”:尝试对经过测试的文件执行ftp_rename()。样本将是:

$result = ftp_rename($connection, $testedFile, $testedFile);

如果失败,那么我们很可能不存在文件。除非您确定权限问题,否则不是100%。但如果它会成功 - 那么文件肯定存在。我怀疑还有另一种方法可以使用,并允许您避免文件传输到本地FS或处理完整目录列表。

答案 2 :(得分:0)

file_exists()或其他stat()系列函数怎么样? FTP包装器支持它。

http://www.php.net/manual/en/wrappers.ftp.php