PHP Check if the file exists on the FTP server without SIZE support.

Yes, I know, it's hard to believe that these FTP servers still exist, but in fact they do. IBM iSeries servers run these servers.

I already have an answer that includes ftp_nlist and in_array , but as some of you may have guessed, it is slow when the directory contains a large number of items.

Due to the lack of SIZE support, fopen always fails when used in read mode (remember that x not supported by the FTP wrapper), and ftp_size always returns -1 (this was expected) and file_exists always returns false (possibly because it uses SIZE internally?).

  • ftp_get and ftp_fget do the trick, but they download the whole file if it exists. Not very good. One possible solution is to use ftp_fget send a file handler that is open only in read mode and to capture the raised warning. Another thing is when the file does not exist, but this solution seems uncouth, and I really don't know if this is possible (maybe someone can give an example).

  • Another solution uses ftp_nb_get / ftp_nb_fget to try to extract the file. If the function returns 0 ( FTP_FAILED ), then the file does not seem to exist. I still have to deal with a temporary local file, and it sucks in to close and reopen the connection if FTP_MOREDATA returned (or other FTP commands cannot be issued).

Do you have any ideas for this?

+8
php ftp
source share
3 answers

SIZE command is not required. You can simply use the ftp_nlist() function to do this because the FTP LIST command allows you to transfer the directory as well as the file as an argument.

Although the PHP documentation does not mention that it is specified in RFC 959 (page 32) and it works. Here is an example. (Thanks 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"; } } 

Or, expressed as a function:

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

In the comments there was a discussion of how useful and reliable LIST results can be. Let me say a few additional sentences to this ...

Creating files on the server

Please note that you should avoid relying on something like:

 if(file_not_exists_on_server($filename)) { create_file_on_server($filename); } 

because it is possible that the file will be created by another client between the first and second functions. Although this is true for local file systems, it can happen in distributed client server applications more easily, due to the longer response time compared to the local file system, and because of the possibly many even anonymous clients (for example, in the example above)

When creating files remotely, I suggest that you follow a strong naming scheme in public folders for writing to avoid collisions. Following this pattern, just write and don't care. The worst thing that can happen is that you are rewriting something that someone else accidentally created. But who creates something like /client/id/file_name.txt accident?


Download files from the server or move, delete files on the server

When you try to perform one of these operations, it does not matter if the files exist or not before the operation. Just do it. But if this fails, you need to handle the errors correctly.

+4
source share

You can use some kind of "dirty trick": try doing ftp_rename() on the verified file. The sample will look like this:

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

if this fails, then we most likely have a nonexistent file. This is not 100% if you are not sure about permission issues. But if it succeeds then the file definitely exists. I doubt that there is another way that you can use to avoid transferring files to a local FS or with a full list of directories.

+2
source share

What about file_exists () or other stat () functions? FTP wrapper supports it.

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

0
source share

All Articles